**ATTENTION!!*Trying to work out a way to contact you but for now I will just post it here:
You have done a good job, just a few things that could be optimized and improved to make the whole game code run even faster and fix the diagonal glide issue, I write highly optimized solutions in C# and I saw this and found a few things to improve for you, Not sure how to contact you so I will post the new version here as a comment but as an overview it now does the following:
1.) I replaced the UBYTE flags with bitflags to decrease memory usage and also uses the efficency of bitwise operations rather than checking a bool for each direction
2.) I Precomputed the tile positions (`left_tile`, `right_tile`, `top_tile`, `bottom_tile`) to avoid redundant calculations.
3.) I Improved the flow of the code logic
4.) I Removed loops in collision detection by directly checking relevant tiles. (MAJOR SLOWDOWN)
5.) I Directly set the players position using addition and subtraction the fastest arithmetic for GB
6.) I Combined conditions using bitwise operations to minimize the number of conditional checks.
Thank you so much! That is amazing. I don't really know c# that well. I will update this as soon as I am able. I'll make it plugin style also so no eject engine is needed.
To reach me: hadrianlingames (ayyyyyyaaat) geeeemail
← Return to asset pack
Comments
Log in with itch.io to leave a comment.
**ATTENTION!!*Trying to work out a way to contact you but for now I will just post it here:
You have done a good job, just a few things that could be optimized and improved to make the whole game code run even faster and fix the diagonal glide issue, I write highly optimized solutions in C# and I saw this and found a few things to improve for you, Not sure how to contact you so I will post the new version here as a comment but as an overview it now does the following:
1.) I replaced the UBYTE flags with bitflags to decrease memory usage and also uses the efficency of bitwise operations rather than checking a bool for each direction
2.) I Precomputed the tile positions (`left_tile`, `right_tile`, `top_tile`, `bottom_tile`) to avoid redundant calculations.
3.) I Improved the flow of the code logic
4.) I Removed loops in collision detection by directly checking relevant tiles. (MAJOR SLOWDOWN)
5.) I Directly set the players position using addition and subtraction the fastest arithmetic for GB
6.) I Combined conditions using bitwise operations to minimize the number of conditional checks.
TopDown.c
#pragma bank 255
#include "data/states_defines.h"
#include "states/topdown.h"
#include "actor.h"
#include "camera.h"
#include "collision.h"
#include "data_manager.h"
#include "game_time.h"
#include "input.h"
#include "trigger.h"
#include "math.h"
#include "vm.h"
#ifndef INPUT_TOPDOWN_INTERACT
#define INPUT_TOPDOWN_INTERACT INPUT_A
#endif
UBYTE topdown_grid;
void topdown_init(void) BANKED
{
camera_offset_x = 0;
camera_offset_y = 0;
camera_deadzone_x = 0;
camera_deadzone_y = 0;
if (topdown_grid == 16)
{
// Snap to 16px grid
PLAYER.pos.x = ((PLAYER.pos.x >> 8) << 8);
PLAYER.pos.y = ((PLAYER.pos.y >> 8) << 8) + 128;
}
else
{
PLAYER.pos.x = ((PLAYER.pos.x >> 7) << 7);
PLAYER.pos.y = ((PLAYER.pos.y >> 7) << 7);
}
}
// Direction flags
#define DIR_FLAG_UP 0x01
#define DIR_FLAG_RIGHT 0x02
#define DIR_FLAG_DOWN 0x04
#define DIR_FLAG_LEFT 0x08
UBYTE dir_pressed;
UBYTE dir_blocked;
void topdown_update(void) BANKED
{
actor_t* hit_actor;
direction_e new_dir = DIR_NONE;
// Check if player is aligned on grid
if ((topdown_grid == 16 && ON_16PX_GRID(PLAYER.pos)) || (topdown_grid == 8 && ON_8PX_GRID(PLAYER.pos)))
{
// Reset movement flags
player_moving = FALSE;
dir_pressed = 0;
dir_blocked = 0;
// Handle input
if (INPUT_UP)
{
dir_pressed |= DIR_FLAG_UP;
new_dir = DIR_UP;
}
if (INPUT_RIGHT)
{
dir_pressed |= DIR_FLAG_RIGHT;
new_dir = DIR_RIGHT;
}
if (INPUT_DOWN)
{
dir_pressed |= DIR_FLAG_DOWN;
new_dir = DIR_DOWN;
}
if (INPUT_LEFT)
{
dir_pressed |= DIR_FLAG_LEFT;
new_dir = DIR_LEFT;
}
// Precompute positions
INT16 player_x = PLAYER.pos.x;
INT16 player_y = PLAYER.pos.y;
UBYTE left_tile = ((player_x >> 4) + PLAYER.bounds.left) >> 3;
UBYTE right_tile = ((player_x >> 4) + PLAYER.bounds.right) >> 3;
UBYTE top_tile = ((player_y >> 4) + PLAYER.bounds.top) >> 3;
UBYTE bottom_tile = ((player_y >> 4) + PLAYER.bounds.bottom) >> 3;
// Collision checks
if (dir_pressed & DIR_FLAG_UP)
{
UBYTE collision = tile_at(left_tile, top_tile - 1) | tile_at(right_tile, top_tile - 1);
if (collision & COLLISION_BOTTOM)
dir_blocked |= DIR_FLAG_UP;
}
if (dir_pressed & DIR_FLAG_RIGHT)
{
UBYTE collision = tile_at(right_tile + 1, top_tile) | tile_at(right_tile + 1, bottom_tile);
if (collision & COLLISION_LEFT)
dir_blocked |= DIR_FLAG_RIGHT;
}
if (dir_pressed & DIR_FLAG_DOWN)
{
UBYTE collision = tile_at(left_tile, bottom_tile + 1) | tile_at(right_tile, bottom_tile + 1);
if (collision & COLLISION_TOP)
dir_blocked |= DIR_FLAG_DOWN;
}
if (dir_pressed & DIR_FLAG_LEFT)
{
UBYTE collision = tile_at(left_tile - 1, top_tile) | tile_at(left_tile - 1, bottom_tile);
if (collision & COLLISION_RIGHT)
dir_blocked |= DIR_FLAG_LEFT;
}
// Determine if movement is possible
if (dir_pressed && !(dir_pressed & dir_blocked))
player_moving = TRUE;
else
dir_pressed = 0; // Prevent movement if blocked
// Update direction animation
if (new_dir != DIR_NONE)
actor_set_dir(&PLAYER, new_dir, player_moving);
else
actor_set_anim_idle(&PLAYER);
// Interaction handling
if (IS_FRAME_ODD)
{
// Check for actor overlap
hit_actor = actor_overlapping_player(FALSE);
if (hit_actor && hit_actor->collision_group)
player_register_collision_with(hit_actor);
}
if (player_moving)
{
hit_actor = actor_in_front_of_player(topdown_grid, FALSE);
if (hit_actor)
{
player_register_collision_with(hit_actor);
actor_stop_anim(&PLAYER);
player_moving = FALSE;
dir_pressed = 0;
}
}
if (INPUT_PRESSED(INPUT_TOPDOWN_INTERACT))
{
hit_actor = actor_in_front_of_player(topdown_grid, TRUE);
if (hit_actor && !hit_actor->collision_group)
{
actor_set_dir(hit_actor, FLIPPED_DIR(PLAYER.dir), FALSE);
player_moving = FALSE;
if (hit_actor->script.bank)
script_execute(hit_actor->script.bank, hit_actor->script.ptr, 0, 1, 0);
}
}
}
if (player_moving)
{
// Cache player position
INT16 player_x = PLAYER.pos.x;
INT16 player_y = PLAYER.pos.y;
UBYTE speed = PLAYER.move_speed;
// Update positions
if (dir_pressed & DIR_FLAG_RIGHT)
player_x += speed;
if (dir_pressed & DIR_FLAG_LEFT)
player_x -= speed;
if (dir_pressed & DIR_FLAG_UP)
player_y -= speed;
if (dir_pressed & DIR_FLAG_DOWN)
player_y += speed;
// Write back updated position
PLAYER.pos.x = player_x;
PLAYER.pos.y = player_y;
}
}
Thank you so much! That is amazing. I don't really know c# that well. I will update this as soon as I am able. I'll make it plugin style also so no eject engine is needed.
To reach me:
hadrianlingames (ayyyyyyaaat) geeeemail
Any chance of updating this to 3+?
I'm a bit rusty now with GB Studio but I'll try and do this once I have a chance
Hey, updated now
Beautiful <3