Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

8 years ago by Arantor

I've mentioned this before, in passing, but I'm happy to show off what I have thus far in case anyone's interested.

It started out as a Datastorm clone (it's a 1988 Amiga game that's a Defender variant), and for the current testing purposes I have ahem borrowed Datastorm's player-ship, lander and bullets.

The two things I really wanted to get right at this stage were the wraparound scrolling (it's a 1920 wide playing area, looped) and the radar, needless to say things like proper collision detection or enemy logic are minor things right now. Proper playability is nil, and I'm not entirely happy with the way the player moves either, but that'll get fixed in time.

So, without further ado, http://arantor.org/datastorm-render-demo/ - this link will at some point be replaced with a proper link to the game when it gains its own identity and be posted on whatsthatgame.co.uk, but for now, that is what it is. At the same time I'll also change the graphics too, to ones that suit the game overall.

The implementation in places is still raw and naive in places but it works.

Controls are arrows, X to fire, A to autofire reload (more on this later)

As far as implementing things goes, there is a custom entity called a Dsentity, from which everything inherits. The two key differences compared to a normal entity at this point are that it has its own update logic that runs after the normal update logic, and a custom draw routine (which breaks the debugger facilities for hitboxes etc.) - it just felt like a cleaner way that using a plugin and injecting into Impact.Entity.

The playfield is as you might expect a 0-1919 area and entity positions are considered normally, with the exception that if an entity leaves one edge (x <0 || x > 1919), the Dsentity update moves it around to the other edge allowing for velocity etc.

The custom draw then resolves screen position and draws it in the right place - note that I do not ever change screen.x or worry about the normal drawingPos routines, simply because while sometimes I'll be drawing things reasonably normally, sometimes I'm drawing stuff that the engine considers would be 'off screen' so I ignore that and do all my own drawing.

As for the radar, there's a second canvas who starts off receiving the background image, then getImageData is called, and we step through all the entities that have a colour defined (the ground doesn't, and bullets don't) and entities that have a colour, their position is divided by 10 (since the radar is 192x20 compared to the main area of 1920x200) and the relevant pixel is updated in the image data, before we transfer that wholesale (and doing the rescaling to main canvas scale in the process) to the main canvas, so we get the 2x scaling for little code effort, and almost certainly less effort overall than drawing the 2x2 pixels manually, or drawing an image for each enemy on the radar. (And it amounts to two draws per frame, but they're ones that aren't going to be accounted for in the debug panel, but that's cool.)

There's a few other things I've experimented with to see what happens, namely 'autofire', which is an ammo based autofire facility (like Datastorm had), whereby it spits out a bullet each frame, meaning there can be dozens of entities added to the screen. Press A to reload 500 rounds into the autofire (normally you'd collect a powerup but this is for debugging) and then you can just hold X to autofire a bullet per frame while X is held down. The result is to see how well handling dozens of new entities works out both in terms of handling the update and the draw cycle, but so far it doesn't seem to cripple things either way.

Also note that the movement is a bit special (and has legacy code that needs pruning) - essentially the idea is that if you're moving, you're moving under thrust and that your ship is dealing with the inertia for you, so that moving is basically direct control, but if you let go, certain things happen - namely that the ship can continue left/right for a short while (under friction), and that gravity can take effect too. The up/down movement's a bit fast but I'm working on that. Also, the ground is bouncy, but not quite bouncy enough yet ;) It too is an entity for all the same custom drawing requirements.

All in all, I'm pretty happy with it so far, the bigger thing is to decide exactly what directions to go with this now the very core mechanics have been settled (though there is still occasionally a very slight visual blip if you happen to shoot an enemy under specific circumstances while they cross the 0/1920 line, but you generally don't notice it because of their movement, the bullet's movement etc. the collision generally works as expected.


And yes, that sparkly rainbow ground exists solely so that I could validate the movement was silky smooth (it runs from red through all the colours and back to red, so red is the crossover point)

8 years ago by Xander

Very nice work. I destroyed all of the aliens and saved the universe.

Looks pretty smooth, as you say. Well done!

8 years ago by Arantor

Tonight this came back to bite me - that part about shooting an enemy over the 0/1920 line, or in fact collision being basically broken around there.

So I've just spent the evening rewriting collision handling. For anyone wondering what I've done, it's a multi-step process.

The first thing is to essentially normalise everything in a single consistent manner. Anything that's at x = 0 or up is normally fine, until you get to pos.x + size.x > 1920. What happens is that in my base magic entity, not only does it account for movement either side of the 0/1920 line, but now it also precalculates the 'normalised' x and x+width values, which is not the same as the draw position. The draw position is simply that if the x pos goes over the line, move the entity to the other side (i.e. pos.x = (pos.x + 1920) % 1920) while this normalises things so if the entity's position puts any part of it beyond the 1920 line, the normalised collision position is pos.x - 1920.

Anyway, once we have the normalised collision position, we also update the master touches() function for the entities to use this normalised position. Note that we've already stored the normalised pos.x + size.x which simplifies the touches function slightly, which has a nice performance aspect.

Lastly, we also replace the main game's checkEntities() routine to use the collision-normalised positions. It's really no different to the standard ig.Game version except for replacing the xmin and xmax definitions with ones that use the normalised positions.

It sounds very complicated, and to a point it is, but if anyone else attempts something like this, hopefully it'll help :)



EDIT: And then I realise that it still doesn't work properly for some cases, which this logic won't solve >_< That'll teach me for showing off!

7 years ago by jessefreeman

I just started doing some research into doing something like this for my next game. Were you able to sort out your collision issues? I was also curious if you were going to post the source code or if it could be turned into a plugin?
Page 1 of 1
« first « previous next › last »