Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

**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;

  }

}

(1 edit)

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