First Devlog :)
https://loganjbp.notion.site/133deb2031db80be9825e8b546fe0b1b?pvs=4
Over the last week and a bit, I started making my first Godot game. The concept of the game is a multiplayer parkour game where you and your teammates need to try to score the ball into the other team’s goal, I plan to add teams of one, two or three with online support and an emphasis on trick shots with the ball in order to score.
So far this week I have created a tile set, character controller with temporary visuals and the ball which can be picked up and thrown. I also started working on a dynamic camera but I haven’t got it working properly.
-
Character:
This is a modified and upgraded version of the character from the Brackey’s tutorial game. It was created entirely by me as an attempted remake of my scratch platformer movement that you can see in Rift Brawl. It’s not the most complex thing ever but I like the slight momentum and all of the customisable constants at the top. The animation section at the bottom is basically a sequence of if-else statements checking the player’s state and playing the appropriate animation.
-
Code
racterBody2D @onready var animated_sprite_2d = $AnimatedSprite2D #region variables const speed = 200 const gravity = 20 const jump_force = 500 const slam_force = 2000 const midair_jumps = 1 const midair_jump_force = 400 const friction = 1.3 const max_fall_speed = 3000 const max_x_speed = 7000 const walljump_x = 4 const walljump_y = 1.5 const dash_multiplyer = 5 const slam_jump_multiplyer = 1.5 const floor_speed_multiplyer = 0.6 const wall_slide_speed_multiplyer = 0.8 const ground_dash_x = 5000 var current_air_jumps = 1 var currently_slamming = 0 var ground_dash_cooldown = 0 var midair_dash = 0 #endregion func _physics_process(_delta): #region MidairDash / WallJump midair_dash -= 0.1 if !is_on_floor(): velocity.y += gravity if velocity.y > max_fall_speed: velocity.y = max_fall_speed if currently_slamming < 0 and Input.is_action_just_pressed("Jump"): if is_on_wall_only(): current_air_jumps = midair_jumps velocity.y = -jump_force * walljump_y velocity.x = jump_force * walljump_x move_and_slide() if is_on_wall(): velocity.x = jump_force * (0 - walljump_x) elif !current_air_jumps == 0: velocity.x *= dash_multiplyer velocity.y = -midair_jump_force current_air_jumps = current_air_jumps - 1 midair_dash = 2 #endregion #region Jump if is_on_floor(): current_air_jumps = midair_jumps if Input.is_action_pressed("Jump"): if currently_slamming > 0: velocity.y = -jump_force * slam_jump_multiplyer currently_slamming = -1 else: velocity.y = -jump_force else: currently_slamming -= 0.1 #endregion #region Slam if !is_on_floor() && Input.is_action_just_pressed("Down") && currently_slamming < 0: currently_slamming = 1 # Engine.time_scale = 0.2 #slowdown effect await get_tree().create_timer(0.05).timeout Engine.time_scale = 1 velocity.y = slam_force currently_slamming = 1 #endregion #region GroundDash if is_on_floor() && Input.is_action_just_pressed("Down"): if !abs(velocity.x) < 1 && ground_dash_cooldown < 0: velocity.x = (velocity.x / abs(velocity.x)) * ground_dash_x ground_dash_cooldown = 2 ground_dash_cooldown -= 0.1 #endregion #region HorizontalMovement if is_on_floor(): var horizontal_direction = (Input.get_axis("Left","Right")) * floor_speed_multiplyer velocity.x = ((velocity.x + (speed * horizontal_direction)) / friction) else: var horizontal_direction = (Input.get_axis("Left","Right")) velocity.x = ((velocity.x + (speed * horizontal_direction)) / friction) if is_on_wall_only() && velocity.y > 0 && currently_slamming < 0: velocity.y = velocity.y * wall_slide_speed_multiplyer if abs(velocity.x) > max_x_speed: velocity.x = (velocity.x / abs(velocity.x)) * max_x_speed #endregion #region Animations if velocity.x > 0: animated_sprite_2d.flip_h = false animated_sprite_2d.offset.x = abs(animated_sprite_2d.offset.x) else: animated_sprite_2d.flip_h = true animated_sprite_2d.offset.x = 0 - abs(animated_sprite_2d.offset.x) if is_on_wall_only() && currently_slamming < 0: animated_sprite_2d.play("Wallslide") elif midair_dash > 0 and abs(velocity.x) > 10: animated_sprite_2d.play("DashAir") elif ground_dash_cooldown > 0: animated_sprite_2d.play("DashGround") elif currently_slamming > 0: animated_sprite_2d.play("Slam") elif is_on_floor(): if !Input.get_axis("Left","Right") == 0: animated_sprite_2d.play("Run") else: animated_sprite_2d.play("Idle") else: if velocity.y < 0: animated_sprite_2d.play("Rise") else: animated_sprite_2d.play("Fall") #endregion GlobalScript.player_x = position.x GlobalScript.player_y = position.y GlobalScript.player_x_vel = velocity.x GlobalScript.player_y_vel = velocity.y move_and_slide()
-
Sprites
-
-
Ball:
The ball is quite basic, as Godot comes with an object called “RigidBody2D,” which does all of the ball physics for me. Because of this, the only coding I needed to do was about picking up and throwing the ball. It's very messy, and there are probably far easier methods, but it gets the job done. When thrown, the ball will move in the direction chosen by the player via the movement keys added on top of the player’s velocity to make it feel more natural.
-
Code
extends RigidBody2D var touching_player = 0 var holding_ball = 0 var key_down = 0 @onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D func _ready() -> void: linear_velocity.x = randf_range(-1000,1000) func _on_area_2d_area_entered(area: Area2D) -> void: touching_player = 1 func _on_area_2d_area_exited(area: Area2D) -> void: touching_player = 0 func _physics_process(_delta): if touching_player == 1: if Input.is_action_just_pressed("Throw") && holding_ball == 0: key_down = 1 holding_ball = 1 if holding_ball == 1: position.x = GlobalScript.player_x position.y = GlobalScript.player_y if Input.is_action_just_pressed("Throw") && key_down == 0: linear_velocity.x = 0 linear_velocity.y = 0 holding_ball = 0 key_down = 100 linear_velocity.x = (Input.get_axis("Left","Right") * 1000) + GlobalScript.player_x_vel linear_velocity.y = (Input.get_axis("Jump","Down") * 1000) + GlobalScript.player_y_vel linear_damp = 0 else: key_down = 0 GlobalScript.ball_x = position.x GlobalScript.ball_y = position.y
-
Sprite
Made by my friend Max, the sprite is quite basic but I think it looks really nice.
-
-
Visuals:
Whilst it all needs a lot of work, I think the tiles turned out great. I made them using Piskel, a free pixel art tool and I made a lot of use of the lighten and darken tool to add shading which greatly improved the style. I was aiming for a vaguely sci-fi theme with a lot of contrast and shadows.
-
Camera:
A good camera is something that will make or break a game like this, I want the camera to show all important info whilst also not permanently being incredibly zoomed out. I started this by creating a node that will sit directly between the player and the ball, this will keep them cantered if they are touching and keep the camera in the right place to show both when it’s not. The hard part was trying to set the camera zoom to an appropriate zoom to keep everything on screen. As of now, this system isn’t done and if I’m honest I don’t know how my barely functional code works so I will need to completely redo it at some point.
- Code
- extends Node2D @onready var camera_2d: Camera2D = $Camera2D func _process(delta: float) -> void: position.x = (GlobalScript.player_x + GlobalScript.ball_x) / 2 position.y = (GlobalScript.player_y + GlobalScript.ball_y) / 2 if abs(GlobalScript.player_y - GlobalScript.ball_y) > abs(GlobalScript.player_x - GlobalScript.ball_x): camera_2d.zoom.x = ((1 - (abs(GlobalScript.player_y - GlobalScript.ball_y) * (0.0003555556 * 0.5))) * 0.8) else: camera_2d.zoom.x = ((1 - (abs(GlobalScript.player_x - GlobalScript.ball_x) * (0.0003555556 * 0.5))) * 0.8) if camera_2d.zoom.x < 0.3: camera_2d.zoom.x = 0.3 camera_2d.zoom.y = camera_2d.zoom.x
Get Rift Slam Beta
Rift Slam Beta
godot multiplayer team game. without the multiplayer or teams yet! (first try at a real godot game)
Comments
Log in with itch.io to leave a comment.
The formatting on the code isn't messed up if you go to the link at the top