Hello, everyone!
I am very new to this and not a good programmer in general (language comes much more naturally to me than maths) so I need your help. I'm making my first PICO-8 game. It's a WWII submarine simulation game where you have a top-down view of your sub. You can dive (which just hides the boat) and fire torpedoes. I have most of the graphics done. What I need your help with is this:
How do I rotate the game world around my boat and keep track of enemy ships I spawn? The game world itself is empty (it's just the blue ocean). But I want to spawn in ships randomly off screen and then have them move slowly across the game world. And I want my boat to be able to turn around slowly with the camera locked to the boat. I've decided the boat will just move at a fixed pace so all the turning is doing is changing the view of the world (which is what you see on screen). I might actually just fake movement of the player boat by moving the enemy ships in a relative direction accordingly.
Let's assume the boat isn't moving. I can tackle that later, when I have this other stuff in place. How do I define a section of ocean a few screens wide in all directions and then spawn enemies there? And how do I rotate the view around the sub (including the enemy sprites) and then keep track of their position relative to the rotating camera?
If anyone has links to tutorials that explain at least part of this, I'd be grateful. I've been looking around in vain for a while for things that come close to explaining what I want to do here.
If anyone wants a look at the code I have so far, knock yourself out. It's just some basic drawing graphics on screen stuff. You can tell the aesthetics I'm going for from it, though:
Well, I've decided to go for a more traditional model and actually use the built-in map and to move my boat around that. I have described my thinking in detail on my blog.
fab.industries: Game Development with PICO-8, Part 2
If anyone has any further pointers, I would appreciate any help I can get very much!
It looks like you no longer need an explanation of how to rotate a game world, but in case anyone else stumbles on this thread, I'll go ahead and answer how the rotating world version could be done. However, I will give one piece of advice for both you and anyone else that wants to rotate sprites in a 2d video game: make the "position" of in-game objects represent the center of their sprite. There are many many cases where you will get in a quagmire otherwise. For example, if you have a sprite that is 8x8 as usual, it should be rendered at (x-4, y-4) unless the individual object is actually smaller with a less relevant bit sticking out (like an eyeball with a dangling bit). Rotations that aren't around the center of something are hell.
Basically, keeping track of things in a game world is always just about keeping track of lists of things and where they are. How you portray them during rendering doesn't change that unless you need some extreme optimization to get them to render fast enough. As such, each enemy would just need basic info in some form: x and y for position, direction and speed and/or dx and dy for movement (using both just allows you to save on calculations when they don't change), then things like hp and ammo for the game mechanics.
From there, the process of figuring out how to show the enemies from the player's view takes three steps, each using either local variables or variables stored under different names so that they don't interfere with the mechanics. 1. the positions need to be shifted to pretend the player's ship is the origin. This is done by just subtracting the player's x and y from the x and y of the enemy. 2. the new enemy position needs to be rotated by the current camera angle. Wikipedia has an article called "Rotation matrix" that explains how to do this, and also conveniently gives a straight-forward formula for each. It relies on using normal coordinates (with y going up when positive) and also on the rotation being counterclockwise starting from directly to the right, but simply testing values will reveal how it needs to be adjusted. Those formulas are x_new = x cos(a) - y sin(a) and y_new = x sin(a) + y cos(a). 3. the rotated coordinates need to be shifted again to compensate for the player not being at the origin on-screen. This is handled by adding the player's on-screen x and y to get the final x and y values for the enemy.
Typically these are referred to as model, world and camera transforms, but I can never remember which name goes to which step.
using e as a table containing an enemy's info and p as a table containing the player's info, cx/cy being the position of the player on-screen, tx/ty being temporary values and rx/ry being the position to render to, here what it looks like in code:
local rx = e.x local ry = e.y rx = rx - p.x ry = ry - p.y local tx = rx * cos(p.dir) - ry * sin(p.dir) local ty = rx * sin(p.dir) + ry * cos(p.dir) rx = tx + cx ry = ty + cy |
Lastly, the amount to rotate each enemy sprite by would just be their direction plus the camera direction.
[Please log in to post a comment]