Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411539 Posts in 69383 Topics- by 58439 Members - Latest Member: isabel.adojo

May 02, 2024, 05:04:19 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsSpooky Pooky
Pages: 1 ... 5 6 [7] 8 9 10
Print
Author Topic: Spooky Pooky  (Read 43344 times)
joeyspacerocks
Level 1
*



View Profile WWW
« Reply #120 on: December 12, 2015, 03:20:03 PM »

Spooky Pooky finally has some audio in it.

After a bit of thrashing about trying to decide between straight OpenAL, FMod, Wwise, random wrapper libraries and SFML I fell off my toilet, banged my head and had an epiphany.

Once I cleaned that up I just chucked SFML in there and never looked back. Currently using GLFW to get a window + OpenGL context set up, so I'll probably ditch that and use SFML there too - no point having two libraries.

For iOS I'll just use the CoreAudio / OpenAL code I've used for my previous game (QB1-0) as it's pretty easy when it's just one platform to worry about.

Like a lot of non-audio people I find adding sound to games pretty daunting - but to be honest it's like lots of things, you've just got to start doing something and let it grow from there.

So I grabbed a whole bunch of weird samples from 99sounds.com (great resource) and messed about with them in Audacity before chucking them into the game.

My audio wrapper code is very straightforward at the moment - just maintain a map SFML sound buffers and an array of sound instances. I've added some spatial support for sounds on the left/right of the screen are located correctly which seems to work fine.

There's only a few samples in there at the moment, but it really brings the game to life (every one always says this, but it's so true).

Music is an interesting subject. My only musical skill is really the same as my core artistic skill - I really know when the output is a bit crap. I just can't grok proper DAWs - it's like trying to use Photoshop for me; I just don't have the years of using the tools that it really takes to be able to use them properly.

Luckily I stumbled across Bosca Ceoil by Terry Cavanagh and it's so much fun to use. Not sure the results are much good at the moment, but I can get a sense of progress here and some of it's sounding ok. I've put some in the game and it fits reasonably well.

Here's a GIF showcasing the audio:



In other news - I'm rejigging where in the story the game opens. Originally I had the player starting as Horatio in his human form, stumbling across the machine that transforms him. However, Horatio lacks the speed and agility of the skeletal version, and the stage had no clear purpose to the player. So I was worried that the player would get turned off and bored before really getting into it.

So I've decided to start the game with a scene similar to the above - you're an animated skeleton trapped in a glass jar and you don't know why or how you got there. In this first little section you find your brain (or maybe just your hippocampus) whereupon you regain your memory of how you got there.

This part will then be presented as a playable flashback scene detailing Horatio's fall from flesh.

Well it's a plan - being a metroidvania you'll come across the lab + machine area again later in the game.

Oh yeah, one last technological development. There's doors. Look, there's one sliding up there. Everyone loves a game with doors in it.

Adding them was reasonably simple - they're just entities that are solid (for which I had to rejig my collision code, previously only used for tile chunks) with paths and triggers.
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #121 on: December 15, 2015, 01:48:28 PM »

Silly little test to see how an electrical power up would look - i.e. how does the electrical sprite renderer look for small sprites (16x21 in this case):



In a bit of a creative slump at the moment (otherwise known as why the hell am I doing a metroidvania) so trying to jolt myself out of it with a few volts.
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #122 on: January 13, 2016, 01:22:46 AM »

And ... I'm back in the game. Took a little break over Christmas and the neglect caused Spooky Pooky to get very cross with me.

Fired it up and randomly fullscreen was running at about 30fps.

No idea why - MacBookPro retina using GLFW and OGL 3.2. Windowed still worked fine, even a window the same size as fullscreen.

So began a long and ultimately fruitless journey to try and work what the hell was happening. Over Christmas I'd done two things that I thought could be relevant. The first was that I played quite a bit of Elite Dangerous, in full screen. The second was that I plugged my laptop into my Sony TV via HDMI.

Still not understanding the problem I switched the window + context creation code to use SFML (since I was planning to do that anyway) with no discernible difference. Finally I switched vsync off and suddenly it was running at full speed again (actually ridiculous speed, since I'd artificially set delta times to 1/60s to help with debug pauses, so it was blasting along at 7 billion fps).

Anyway, none the wiser really.

Since then I've bypassed the SFML fullscreen mode when running on macs to make the game compatible with OS X fullscreen stuff, meaning I don't have to deal with context recreation (a pain since context sharing doesn't work on OS X with the OGL version I use).

Brilliant. Anyway, mapping the input over to use SFML was trivial so the game is back to running how it should and I can get on with fixing the room transition code.

Originally the game was being written as a level-based thingy - now it's a metroidvania. So levels have become rooms, and it lets you randomly wander between them. It's been fairly easy to transition the game to this. Each room is a Tiled map and I cache them in memory, preserving entity state as you wander between them.

Rooms can be grouped into sections so I may flush whole sections out of memory when you cross the boundary - either way it's a fairly lazy system.
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #123 on: January 19, 2016, 10:17:22 AM »

Sometimes the simplest of things take an age to get working. Like room transitions. As seen in the horribly laggy gif below:



My rooms are stored as separate Tiled maps. There is an entity type called a 'transporter' which has a collision function attached to it. When a player runs into the transporter it assumes control (via a generic target property, and a corresponding owner property in the player entity).

The transporter think function then artificially keeps the player running in the same direction so that they fully enter the entity (thus disappearing out of view).

Once contained it triggers the room change logic, which looks up the destination room in a cache, loading it if not present. Simultaneously a transition effect is played. The rooms are relatively small (a handful of screens typically), so load quickly and are cached in memory.

The player is then attached to the map transporter entity in the new room (as indicated by the destination of the original trigger transporter), and control is given over to that to walk the player fully out and into the level.

The transition effect is lacking at the moment so might tinker about with that in a bit.

It all seems a bit over-complicated but it's flexible and actually straightforward in the code, plus it's driven via the standard collision triggers and think hooks of the rest of the system.
« Last Edit: January 19, 2016, 10:23:07 AM by joeyspacerocks » Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #124 on: January 24, 2016, 09:53:42 AM »

A little update this week.

I've accidentally implemented some kind of poor-man's event system. Dang, half-arsed-framework-evolving-warning.

It all started when I noticed that when the hero is exploded out of a container jar I had no easy (i.e. generic) way of switching his animation from 'look shocked and concerned' to 'act casual and wait to run around'.

So I wanted things to know when they were freed from a container. Things in this eclectic code base are represented by a single struct called an Entity. Until now I had a bunch of function pointers for custom methods to think, render and handle collisions (actually two handlers for this for collisions between entities and collisions between an entity and tiles).

(Did I mention that I'm writing this in C? Ok, ok. I'll be a good chap and won't bang on about it.)

Reluctant to add another function pointer, I've replaced the collision functions with a single event handler pointer that takes an Event structure.

Event types include 'triggered' (bit vague), 'collision', 'tile collision' and now 'contained' and 'released'.

To avoid calling event handlers on things that don't care about events (i.e. most things), entities also specify a bitmask indicating which events they want to be told about. E.g. the player entity has mask of EVT_COLLISION | EVT_RELEASED.

So after all that I now have a logical place to put a bit of code that stops the player looking so worried when he's just exploded out of a jar.

Take heed. This is why games aren't finished.
Logged

teefal
Level 2
**



View Profile
« Reply #125 on: January 24, 2016, 10:03:37 AM »

You're bringing me back to my days of C ... so lean, so precise, so easy to shoot yourself in the foot.

Bullet-proof everything.  Refactor constantly.  Automate testing.   And like you said, slip the schedule Smiley
Logged
oahda
Level 10
*****



View Profile
« Reply #126 on: January 27, 2016, 12:57:18 PM »

Hey, how do your particle systems and their rendering work, and how much do particles affect performance/framerate in your engine?
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #127 on: January 27, 2016, 02:43:03 PM »

Hey, how do your particle systems and their rendering work, and how much do particles affect performance/framerate in your engine?

Hi. They're pretty basic, although separate to other entities in the game.

Each particle is a simple struct containing the usual position, velocity, animation and some behaviour flags.

The animation is the same stuff as used elsewhere - a simple array of frames (coords into a spritesheet / delay) plus some behaviour flags and render depth.

I pre-allocate a pool of particles in the game init code (currently only 5000 big) plus a list that hooks into the pool for active particles (I have simple + fast implementations of pools and linked lists).

Each tick the particles are updated, returned to the pool if expired. Their flags indicate if they need collision detection with the player / world, but most don't (e.g. steam particles collide with the player so that they can be wafted along depending on how fast the player is moving).

When something needs to throw out a bunch of particles it calls some emitter code that generates them, allocating from the pool and adding to the list.

For rendering it all goes into the same batch system that I use for all the other sprites. Each particle can have it's own depth and rendering requirements (e.g. blending mode / alpha) and they just end up sorted into batches with the rest of the stuff and flushed out to OpenGL using as few draw calls as possible.

At the numbers I have in the game at the moment they have a negligible effect on performance - nothing like my previous game, QB1-0:

« Last Edit: January 27, 2016, 02:48:05 PM by joeyspacerocks » Logged

oahda
Level 10
*****



View Profile
« Reply #128 on: January 28, 2016, 04:14:03 AM »

Woah. That's pretty.

So are you still invoking a shader for each individual particle or passing the structs to an array and rendering them all in one go? I tried the latter at first, but when there were only a few particles on screen that usually ended up being slower, because there was so much empty space in the buffer not being used. Now I'm passing every individual particle into a lightweight geometry shader that generated a quad filling up no more than the space each individual particle occupies on screen, so that the following fragment shader need only work on a few fragments for each particle. It's better, but only works okay with a few thousand particles at most. I also can't render different emitters to the same buffer because they have individual layering just like all other game objects.

But you mean the particles in QB1-0 actually dragged performance down a bunch?
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #129 on: January 29, 2016, 04:01:29 AM »

For Spooky Pooky I chuck all sprites to be rendered into a big array - this includes the particles. At the end of the first pass of the rendering process I then sort this array by a few things (depth, blend-mode, shader) then I sweep through it filling up a big interleaved array of data to give to OpenGL.

I flush out this array to OpenGL every time I change the blend-mode or shader. However, at the moment I only really have two shaders - one is just a simple texture-blit (from spritesheet coordinates) which is used for nearly everything. The other is the water shader which blends two textures together with a wibble offset.

The blend mode doesn't change much typically - at the moment I only change it for electrical sparks.

Everything has a depth though so it's possible that I have electrical stuff at multiple depths, which will cause a few flushes.

Typically though most frames are rendered with maybe 6-10 drawcalls (using glDrawArrays with GL_TRIANGLES) to OpenGL.

The actual tilemap I use for the level data also goes into the drawcall and is sorted - this is also rendered with the same texture blit call but from a VBO with static coordinates that covers the whole screen. I offset it by a scroll amount and change the texture coordinates each frame.

So much for Spooky Pooky - QB1-0 was all a lot simpler.

The ships, asteroids, font, etc were drawn with a single call to OpenGL with GL_LINES and the particles where similarly drawn with another call using GL_POINTs.

QB1-0 was only on the iOS though and when I wrote it I was using an iPhone 4 as my base level. So it had to be 60fps on that with no frame dropping. The biggest problem I had was with the 'black-hole' enemy type. These are simple gravitational attractors that basically pull everything on the screen (including particles) towards them.

I decided to render them purely through particles. So they emit particles with a velocity perpendicular to the spin of the entity - this means the particles go into a nice expanding orbit and it ends up being a cool swirly effect. However it took a lot of particles to make it look good, which would sometimes pull the framerate down.

To solve this I have two update functions for particles. If the count is not too high I apply the full physics model to them and let them wrap-round the screen. If the particle count goes too high then particles go through the 'fast' route, where they have a simplified physics model (no attraction) and they stop wrapping the screen and just get returned to the pool when they fall off the edge.

This worked pretty well as if there's that many particles on the screen you can't really tell what's going on anyway Smiley All told I think I had a max limit of about 10,000 particles for that game.

Of course nowadays I'm sure that an iPhone 6 could copy with a lot more ... plus I'm also sure that there's a lot of other things I'm doing wrong Smiley For a start I use linked lists a lot which probably means I get a lot of cache misses (even though the source data for the list is from a big contiguous pool).

Hey-ho life can be too short to worry about that sort of thing until you need to ..
« Last Edit: January 29, 2016, 04:15:42 AM by joeyspacerocks » Logged

oahda
Level 10
*****



View Profile
« Reply #130 on: January 29, 2016, 04:48:03 AM »

Thanks for all the neat info! A little confused by the array passing tho, because of the severe limitations to how many uniforms can be passed to GLSL; wouldn't that limit you to fairly few sprites with each shader call? Do you loop through the array, passing a bit of it at a time, invoking the shader several times until you've covered it all?
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #131 on: January 29, 2016, 05:15:53 AM »

Sorry to confuse Smiley The array I refer to is just the data array of vertex and texture data that I pass to the OpenGL draw call for it to then render the contents of using the shader - it just contains all the triangles + texture coords, etc.

I guess the shader is then just applied for each primitive in the array - in this case triangles.
Logged

oahda
Level 10
*****



View Profile
« Reply #132 on: January 29, 2016, 05:35:35 AM »

Oh, now I get it!
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #133 on: January 31, 2016, 03:34:18 PM »

I was supposed to be working on the structure of the game and power-ups this weekend.

Instead I accidentally made some kind of blobby bouncy mega-caterpillar boss thing.



Um. Oops.
Logged

flipswitchx
Level 3
***



View Profile WWW
« Reply #134 on: January 31, 2016, 05:17:02 PM »

Sweet pixel art sir! That's a real nice bounce to things you've got. Impressed with that caterpillar monster, and those volts! Stunningly cool Smiley
Logged

joeyspacerocks
Level 1
*



View Profile WWW
« Reply #135 on: February 01, 2016, 08:26:23 AM »

Thanks! Appreciate the kind words. At the moment it feels like I'm just churning out GIFs instead of making a game - trying to convince myself that I'm just getting all the mechanics and bits and pieces in place before I assemble it into The Game, but ...
Logged

Zorg
Level 9
****



View Profile
« Reply #136 on: February 07, 2016, 04:01:06 AM »

I'm not sure if i ever posted something here, but i'm always following your updates. Smiley

I have a question:
Quote
The game runs at 480x272 [...]
How did you come up with that resolution? Thats 30:17 (16x16 tiles) which is pretty close but not exactly 16:9. Do you simply cut some pixels vertically (272x4=1088 -> 8 pixels too high) to fit 1080p?

Edit: How do you display your game at a 720p resolution?
« Last Edit: February 07, 2016, 04:17:55 AM by zorg » Logged
joeyspacerocks
Level 1
*



View Profile WWW
« Reply #137 on: February 07, 2016, 02:31:36 PM »

How did you come up with that resolution? Thats 30:17 (16x16 tiles) which is pretty close but not exactly 16:9. Do you simply cut some pixels vertically (272x4=1088 -> 8 pixels too high) to fit 1080p?

You know what? I can't remember. I've just gone to check the source and it looks like I've now settled on 480x279, which is even more random. That puts it at just the other side of 16:9. The only thing I can think is that I was mucking about with this stuff at the same time as I started playing Axiom Verge which also has a resolution of 480x279, so I must've stolen it ... Smiley

Edit: How do you display your game at a 720p resolution?

So when windowed the game runs in a x2 480x279 window. At fullscreen it is letter-boxed by fitting 480 into the horizontal resolution and scaling the vertical by the same ratio - the left-over is black-barred.

The game actually started out as an iOS game and I've been through a raft of resolutions and ratios as it's progressed (as the early screenshots show). It still runs on an iPhone, although the input is a bit banjaxed, so I've still to figure out what I'm going to do with the resolution there ...
Logged

Geoff Moore
Level 3
***


Game composer for hire


View Profile WWW
« Reply #138 on: February 07, 2016, 06:05:58 PM »

This looks adorable! All the shader stuff fits really well with the chunk pixel base, it looks awesome :D
Logged

Composer for multiple Steam and Itch-released indie games. Listen/contact: https://geoffmoore.co.uk

Zorg
Level 9
****



View Profile
« Reply #139 on: February 08, 2016, 12:14:52 AM »

Thanks for elaborating on the resolution topic.

I was checking some pixel platformer devlogs to see how they handle screen resolution and your game stands out. Most of them use a height of 240 (15 stacked 16x16 tiles, NES style), which leads to a factor of 3 for 720 and 4.5 (ignoring the blur for a zoom factor > 4) to 1080. I was wondering if someone uses a 320x180 resolution, which is an odd number (11.25) of 16x16 tiles (vertically) but scales nicely to 1280x720 and 1920x1080. 'Tales of Lena' does. 'There Was A Caveman' uses a resolution of 240x135 zoomed by 2 (480x270) which is pretty close to your resolution, btw. Smiley
Logged
Pages: 1 ... 5 6 [7] 8 9 10
Print
Jump to:  

Theme orange-lt created by panic