So it has been about 2 weeks since my last update on this game. Since that time, I have taken the prototype and created the beginnings of a framework for level design.
In order to make level design easier, I needed to take the single script file I had in my proof and create re-usable objects. Here are the objects I've created so far:
The ship object consists of a sprite, an animation player and a collider. I suspect I may need to expand on this in the future, but for now this covers everything I need. Right now you can't collide with anything, but I plan on having the ship explode on contact with the planet.
I decided to move the gravity code to a different part of the game (the map). The ship itself can alter its "desired vector" based on the rotation and thrust of the ship. This vector gets altered in a different part of the game that actually simulates the gravitational forces.
extends Area2D const TURN_SPEED = 180 # how fast the ship will turn const MOVE_SPEED = 150 # how fast the ship will move const ACC = 0.01 # acceleration % const DEC = 0.01 # deceleration % var motion = Vector2(0,0) # ship's actual move direction (not the desired move direction) onready var animation = get_node("AnimationPlayer") export var fuel = 100.00 func _process(delta): var rotating = false # TURNING if Input.is_action_pressed("ui_left") && fuel > 0: # if the left arrow key is pressed... rotation_degrees -= TURN_SPEED * delta # turn left by TURN_SPEED (* delta, for uniform timing) animation.play("LeftThrust") fuel -= 1 * delta; rotating = true elif Input.is_action_pressed("ui_right") && fuel > 0: animation.play("RightThrust") rotating = true fuel -= 1 * delta; rotation_degrees += TURN_SPEED * delta # MOVEMENT var movedir = Vector2(0,-1).rotated(rotation) # desired move direction if Input.is_action_pressed("ui_up") && !rotating && fuel > 0: animation.play("ForwardThrust") fuel -= 1 * delta; motion = motion.linear_interpolate(movedir, ACC) # lerp towards desired move direction elif Input.is_action_pressed("ui_down") && !rotating && fuel > 0: animation.play("ReverseThrust") fuel -= 1 * delta; motion = motion.linear_interpolate(-movedir, DEC) # lerp towards stillness elif !rotating : #motion = motion animation.play("Idle") position += motion * MOVE_SPEED * delta # move using actual move direction * speed
You can also see at this point I've implemented the animations for Forward, Backwards and Left/Right rotation! I also stopped the ship from shaking when idling. Not really sure what I was thinking when I originally created that animation. Needless to say it looks better now.
I decided to go with an Asteroids like movement style where you can only go forward and backwards with the ability to rotate for a full 360 freedom of motion. This just ended up feeling a lot better once I added the animations.
I still don't know what the exact gameplay is going to be, however I decided to experiment with the concept of fuel. Each thrust reduces your overall fuel until you reach 0. At that point you cannot move the ship at all. I plan on adding fuel stations or canisters to refill when you are low.
The planet object right now only consists of a 2d node and a collider. Each planet has a mass property that I use to determine the size and gravitational force the planet has on the ship.
I still need to figure out how to give planets a scalable texture that looks like pixel art.
I created a script for the overall map that loops through all planets and applies a force to the ship.
Right now I'm still not happy with how the gravity feels. It's difficult to establish a clean orbit around a planet and I can't seem to find a good balance between the ship's thrust and the gravity from the planets. I imagine I will be tweaking this code for a while.
extends Node2D var orbitalBodies =  var GRAVITY_MULTIPLIER = 300 onready var ship = find_node("Ship") func _ready(): for body in find_node("Planets", true, false).get_children(): orbitalBodies.push_back(body) #initiate gravity physics set_process(true) #determines the appropriate acceleration based on relative position and object mass func acceleration(pos1, pos2, mass): var gravity = mass * GRAVITY_MULTIPLIER var direction = pos1 - pos2 var length = direction.length() var normal = direction.normalized() var acc = normal * (gravity / pow(length, 2)) return acc #apply orbital vector to body func step_euler(ship, object): var step = 16 for i in range(step): var dt = ship.ACC/step var acc = acceleration(object.position, ship.position, object.mass) ship.motion = ship.motion + acc * dt ship.position = ship.position + ship.motion * dt #event handler for physics engine func _process(delta): for object in orbitalBodies: step_euler(ship, object) update()
Now that I have a couple mechanics and objects that I can easily use, the next step is for me to figure out the "fun" of the game. I'll be sharing my results (and failures) in the next article.