aboutsummaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
authorUnavailableDev <69792062+UnavailableDev@users.noreply.github.com>2023-03-22 10:45:34 +0100
committerGitHub <noreply@github.com>2023-03-22 10:45:34 +0100
commitd32a4942c7e16af5daf71a769906b17cb44de8e1 (patch)
tree8da86d27d30d841d786a5beca634e3fbaaf00570 /src/engine
parent6d82f9e3d165e0200bed2f2784a1183f47b37fa3 (diff)
parent7f51cd925883bbf958baa289d4d19231667c9eba (diff)
Merge branch 'lonkaars:dev' into dev
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/TODO/combat.h9
-rw-r--r--src/engine/bullet.c44
-rw-r--r--src/engine/bullet.h16
-rw-r--r--src/engine/camera.c35
-rw-r--r--src/engine/camera.h6
-rw-r--r--src/engine/draw_screen.c89
-rw-r--r--src/engine/draw_screen.h26
-rw-r--r--src/engine/engine.c4
-rw-r--r--src/engine/entity.c127
-rw-r--r--src/engine/entity.h82
-rw-r--r--src/engine/level.h5
-rw-r--r--src/engine/maths.c19
-rw-r--r--src/engine/maths.h22
-rw-r--r--src/engine/player_controller.c252
-rw-r--r--src/engine/player_controller.h7
-rw-r--r--src/engine/sprite_controller.c24
-rw-r--r--src/engine/sprite_controller.h118
-rw-r--r--src/engine/title_screen.c93
-rw-r--r--src/engine/title_screen.h3
19 files changed, 981 insertions, 0 deletions
diff --git a/src/engine/TODO/combat.h b/src/engine/TODO/combat.h
new file mode 100644
index 0000000..16c41f5
--- /dev/null
+++ b/src/engine/TODO/combat.h
@@ -0,0 +1,9 @@
+#include "hh_entity.h"
+
+
+// attacktypes:
+
+/// @brief basic attack
+/// @param dmg damage number
+/// @param target entity under attack (damage changes this hp value)
+void hh_attack_basic( int8_t dmg, hh_entity* target );
diff --git a/src/engine/bullet.c b/src/engine/bullet.c
new file mode 100644
index 0000000..5aa9e51
--- /dev/null
+++ b/src/engine/bullet.c
@@ -0,0 +1,44 @@
+#include "bullet.h"
+#include "engine/sprite_controller.h"
+
+
+void shootBullet(vec2 playerPos, Bullet* bullet){
+ // Set bullet's x and y coordinates to player's coordinates
+ bullet->x = playerPos.x;
+ bullet->y = playerPos.y;
+ // Set bullet's velocity to a fixed value
+ bullet->velocity = 1;
+ // Set bullet's status to active
+ bullet->isActive = true;
+}
+void updateBullet(Bullet* bullet, int deltaTime){
+ // Only update bullet if it is active
+ static int latestLocationBullet = 0;
+ if (bullet->isActive) {
+ // Move bullet based on velocity and deltaTime
+ bullet->x += bullet->velocity * deltaTime;
+ drawBullet(bullet);
+ // Check if bullet has moved 16 pixels
+ if (bullet->x - latestLocationBullet > 32) {
+ // Set bullet's status to inactive
+ bullet->isActive = false;
+ drawBullet(&(Bullet){.x = -16,.y = -16. });
+ }
+ }
+ else{
+ latestLocationBullet = bullet->x;
+ }
+}
+void drawBullet(Bullet* bullet){
+
+
+ hh_ppu_update_foreground(10, (hh_s_ppu_loc_fam_entry)
+ {
+ .position_x = bullet->x,
+ .position_y = bullet->y,
+ .horizontal_flip = false,
+ .vertical_flip = false,
+ .palette_index = 7,
+ .tilemap_index = 84, // change tilemap to the correct foreground index;
+ });
+}
diff --git a/src/engine/bullet.h b/src/engine/bullet.h
new file mode 100644
index 0000000..ad67d84
--- /dev/null
+++ b/src/engine/bullet.h
@@ -0,0 +1,16 @@
+#pragma once
+#include "player_controller.h"
+
+typedef struct {
+ int x;
+ int y;
+ int velocity;
+ int isActive;
+ int hit;
+} Bullet;
+
+
+//Bullet* createBullet(float x, float y, float velocity, float direction);
+void shootBullet(vec2 playerPos, Bullet* bullet);
+void updateBullet(Bullet* bullet, int deltaTime);
+void drawBullet(Bullet* bullet);
diff --git a/src/engine/camera.c b/src/engine/camera.c
new file mode 100644
index 0000000..2c3e517
--- /dev/null
+++ b/src/engine/camera.c
@@ -0,0 +1,35 @@
+#include "engine/camera.h"
+
+#include "ppu/consts.h"
+
+
+vec_cor hh_update_camera(vec_cen new, vec2 min, vec2 max){
+
+ //TODO: change floating point math to fix point math
+ //TODO: remove magic number at y camera offset
+
+ // new = vec_cen2cor(new,(vec2){.x=max.x/2,.y=max.y/2});
+ new = vec_cen2cor((vec2){.x=new.x+(HH_PPU_SPRITE_WIDTH),.y=new.y+(HH_PPU_SPRITE_HEIGHT*8)},(vec2){.x=max.x/2,.y=max.y/2});
+ // new.x = new.x << HH_MATH_FIXED_POINT;
+ // new.y = new.y << HH_MATH_FIXED_POINT;
+ static vec_cor old;
+ // old.x = old.x << HH_MATH_FIXED_POINT;
+ // old.y = old.y << HH_MATH_FIXED_POINT;
+
+ // int16_t some = 0;
+ // some = some <<= HH_MATH_FIXED_POINT-1;
+
+ // Camera smoothing
+ new.x = (int)((float)new.x*0.1f + (float)old.x*0.9f);
+ new.y = (int)((float)new.y*0.1f + (float)old.y*0.9f);
+
+ // old.x = old.x >> HH_MATH_FIXED_POINT;
+ // old.y = old.y >> HH_MATH_FIXED_POINT;
+
+
+ old.x = CLAMP(new.x,min.x,max.x);
+ old.y = CLAMP(new.y,min.y,max.y);
+
+ return old;
+}
+
diff --git a/src/engine/camera.h b/src/engine/camera.h
new file mode 100644
index 0000000..b3ffb52
--- /dev/null
+++ b/src/engine/camera.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "engine/maths.h"
+
+vec_cor hh_update_camera(vec_cor new, vec2 min, vec2 max);
+
diff --git a/src/engine/draw_screen.c b/src/engine/draw_screen.c
new file mode 100644
index 0000000..0c31bf6
--- /dev/null
+++ b/src/engine/draw_screen.c
@@ -0,0 +1,89 @@
+#include "engine/draw_screen.h"
+#include "engine/sprite_controller.h"
+
+uint8_t hh_world_to_tile(vec2 pos){
+ //TODO: remove magic file name here
+ FILE* level = fopen("static/level1_test.bin", "rb"); /* open binary file */
+ if (!level) { /* check if file opened successfully */
+ fprintf(stderr, "Error: Failed to open file.\n");
+ return 0;
+ }
+ int index = ((pos.y/16)*40 + pos.x/16);//TODO: remove magic number(s)
+ fseek(level, (index * sizeof(int)) + sizeof(int), SEEK_SET);
+ int tile;// = (int*)malloc(sizeof(int));
+ fread(&tile, sizeof(int), 1, level); // read 1 tile from binary
+
+ fclose(level);
+ // int val = tile;
+ // free(tile);
+ return tile;
+}
+
+
+// remeber old value to know which part to update.
+vec2 previousViewport = { .x = 0, .y = 0 };
+void hh_draw_screen(vec_cor viewport){
+ if (viewport.x == previousViewport.x && viewport.y == previousViewport.y) return;
+
+ hh_ppu_update_aux((hh_s_ppu_loc_aux){
+ .bg_shift_x = viewport.x,
+ .bg_shift_y = viewport.y,
+ .fg_fetch = 0,
+ .sysreset = 0,
+ });
+
+ // update previous viewport values
+ previousViewport = viewport;
+}
+
+void hh_setup_screen(){
+ //(HH_map_size_X*HH_map_size_Y)
+ int size = 2400; // max X = 40 en max Y = 80
+ //TODO: remove magic file name here
+ FILE* level = fopen("static/level1_test.bin", "rb"); /* open binary file */
+ if (!level) { /* check if file opened successfully */
+ fprintf(stderr, "Error: Failed to open level file.\n");
+ return;
+ }
+ fseek(level, (0* sizeof(int)) + sizeof(int), SEEK_SET);
+ int* tile = (int*)malloc(size*sizeof(int));
+ fread(tile, sizeof(int), size, level); // read 1 tile from binary
+
+ fclose(level);
+
+ for(int BAM_index = 0; BAM_index < size; BAM_index++){
+ hh_ppu_update_background(BAM_index, (hh_s_ppu_loc_bam_entry){
+ .horizontal_flip = false,
+ .vertical_flip = false,
+ .palette_index = hh_get_palette(tile[BAM_index]),
+ .tilemap_index = tile[BAM_index],
+ });
+ }
+ free(tile);
+}
+void hh_clear_screen(){
+ // (HH_PPU_SCREEN_HEIGHT*HH_PPU_SCREEN_WIDTH)/(HH_PPU_SPRITE_HEIGHT*HH_PPU_SPRITE_WIDTH)
+ for (int i = 0; i < HH_PPU_BG_CANVAS_TILES_H*HH_PPU_BG_CANVAS_TILES_V; i++) {
+ hh_s_ppu_loc_bam_entry temp = {
+ .vertical_flip=false,.horizontal_flip = false,
+ .palette_index = 3,.tilemap_index = 0
+ };
+ hh_ppu_update_background(i,temp);
+ hh_ppu_update_color(3,0,(hh_ppu_rgb_color_t){0x0,0x0,0x0});
+ }
+ hh_ppu_update_aux((hh_s_ppu_loc_aux){
+ .bg_shift_x = 0,
+ .bg_shift_y = 0,
+ .fg_fetch = 0,
+ .sysreset = 0,
+ });
+}
+
+void hh_clear_sprite(){
+ for (int i = 0; i < HH_PPU_FG_SPRITE_COUNT; i++) {
+ hh_ppu_update_foreground(i,(hh_s_ppu_loc_fam_entry){
+ .position_x = -16,
+ .position_y = -16,
+ });
+ }
+}
diff --git a/src/engine/draw_screen.h b/src/engine/draw_screen.h
new file mode 100644
index 0000000..95765e5
--- /dev/null
+++ b/src/engine/draw_screen.h
@@ -0,0 +1,26 @@
+#pragma once
+
+
+// every function call for drawing the screen goes here.
+#include "engine/maths.h"
+#include "ppu/consts.h"
+#include "ppu/ppu.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+
+#define HH_map_size_X 80
+#define HH_map_size_Y 60
+
+/** @brief return a single tile from world binary */
+uint8_t hh_world_to_tile(vec2 pos);
+/** @brief shift to level if viewport changed position */
+void hh_draw_screen(vec2 viewport);
+/** @brief send data to BAM memory from binary level */
+void hh_setup_screen();
+/** @brief send black screen to background memory */
+void hh_clear_screen();
+/** @brief clears all sprite data */
+void hh_clear_sprite();
diff --git a/src/engine/engine.c b/src/engine/engine.c
new file mode 100644
index 0000000..799ee7c
--- /dev/null
+++ b/src/engine/engine.c
@@ -0,0 +1,4 @@
+#include "engine/draw_screen.h"
+#include "engine/level.h"
+#include "engine/maths.h"
+#include "engine/sprite_controller.h"
diff --git a/src/engine/entity.c b/src/engine/entity.c
new file mode 100644
index 0000000..535759d
--- /dev/null
+++ b/src/engine/entity.c
@@ -0,0 +1,127 @@
+#include <stdbool.h>
+
+#include "engine/entity.h"
+#include "engine/maths.h"
+
+/*
+ PLAYER: (pos on X)
+ ,___,
+ | |
+ | X |
+ |___|
+
+*/
+
+bool hh_collision(vec_cor pos1, vec2 pos2){
+ if (pos2.x == CLAMP(pos2.x, pos1.x, pos1.x+16)){// hit x
+ return true;
+ }
+
+ if (pos2.y == CLAMP(pos2.y, pos1.y, pos1.y+16)){// hit y
+ return true;
+ }
+ return false;
+}
+
+void hh_solve_collision(vec2 pos_environment, hh_entity* entity){
+ if (!hh_collision(pos_environment,entity->pos))
+ return;
+
+ printf("BONK!/n");
+ // if (entity->vel.y > 0){
+ // entity->pos.y = MAX(entity->pos.y,pos_environment.y);
+ // entity->vel.y = 0;
+ // } else {
+ // entity->pos.y = MIN(entity->pos.y,pos_environment.y);
+ // entity->vel.y = 0;
+ // }
+ // if (entity->vel.x <= 0){
+ // entity->pos.x = MIN(entity->pos.x,pos_environment.x-16);
+ // entity->vel.x = 0;
+ // } else {
+ // entity->pos.x = MAX(entity->pos.x,pos_environment.x+16);
+ // entity->vel.x = 0;
+ // }
+}
+hh_entity hh_background_collision (hh_entity temp_old_entity,hh_entity temp_new_entity){
+
+ temp_old_entity.is_grounded = false;
+
+// solves x collision
+ if (temp_old_entity.vel.x <= 0) {
+ if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_old_entity.pos.y + 0})) ||
+ hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_old_entity.pos.y + 15}))) {
+ temp_new_entity.pos.x = (temp_new_entity.pos.x & ~15) + 16,
+ temp_new_entity.vel.x = 0;
+ }
+ } else {
+ if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 16, .y=temp_old_entity.pos.y + 0})) ||
+ hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 16, .y=temp_old_entity.pos.y + 15}))) {
+ temp_new_entity.pos.x = temp_new_entity.pos.x & ~15, // <-- magic comma, NOT TOUCHY
+ temp_new_entity.vel.x = 0;
+ }
+ }
+
+ //solves y collision
+ if (temp_old_entity.vel.y <= 0) {
+ if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_new_entity.pos.y + 0})) ||
+ hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 15, .y=temp_new_entity.pos.y + 0}))) {
+ temp_new_entity.pos.y = (temp_new_entity.pos.y & ~15) + 16,
+ temp_new_entity.vel.y = 0;
+ }
+ } else {
+ if (hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 0, .y=temp_new_entity.pos.y + 15})) ||
+ hh_colidable(hh_world_to_tile((vec2){.x=temp_new_entity.pos.x + 15, .y=temp_new_entity.pos.y + 15}))) {
+ temp_new_entity.pos.y = temp_new_entity.pos.y & ~15,
+ temp_new_entity.vel.y = 0;
+ temp_old_entity.is_grounded = true;
+ }
+ }
+ temp_old_entity.pos = temp_new_entity.pos;
+ temp_old_entity.vel = temp_new_entity.vel;
+ return temp_old_entity;
+}
+
+hh_entity hh_enemy_collision(hh_entity temp_player, hh_entity temp_enemy){
+
+ bool collide = hh_distance_circles( temp_player.pos, temp_enemy.pos, temp_player.radius, temp_enemy.radius);
+
+ if (collide == true && temp_player.is_hit == false)
+ {
+ temp_player.is_hit = true;
+ //angle = atan2( tempEntity.pos_y - tempPlayer.pos_y, tempEntity.pos_x - tempPlayer.pos_x);
+ if(temp_player.pos.x <= temp_enemy.pos.x) //player left of enemy -- creates flinch movement L or R
+ {
+ // printf("BONK-left!/n");
+ temp_player.vel.y = -5;
+ temp_player.vel.x = -8;
+ } else {
+ // printf("BONK-right!/n");
+ temp_player.vel.y = -5;
+ temp_player.vel.x = 8;
+ }
+ // ghost mode / invulnerable or other things on hit
+ // temp_player.hp--;
+
+ } else {
+ temp_player.is_hit = false;
+
+ }
+
+
+return temp_player;
+}
+
+
+bool hh_distance_circles (vec2 object_1, vec2 object_2, int radius_1, int radius_2){
+ int a_squared = (object_1.x - object_2.x) * (object_1.x - object_2.x);
+ int b_squared = (object_1.y - object_2.y) * (object_1.y - object_2.y);
+ int c_squared = a_squared + b_squared;
+ int radius = ( radius_1 + radius_2) * ( radius_1 + radius_2 );
+
+ if( c_squared <= radius ){
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/engine/entity.h b/src/engine/entity.h
new file mode 100644
index 0000000..cad6ba4
--- /dev/null
+++ b/src/engine/entity.h
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "ppu/types.h"
+
+#include "engine/maths.h"
+
+typedef uint8_t hh_idx_t;
+
+typedef enum {
+ fire, ice, poison
+}hh_e_damage_t;
+
+typedef struct {
+ hh_s_ppu_loc_fam_entry fam; //screen
+ hh_idx_t frame0;
+ hh_idx_t palette;
+
+}hh_s_rendering;
+
+typedef struct {
+ int8_t hp;
+ int8_t dmg;
+ hh_e_damage_t dmg_type;
+ int8_t speed_x, speed_y;
+
+} hh_s_atributes;
+
+
+typedef struct {
+ vec2 pos, vel, vec;
+ bool is_grounded;
+ bool is_hit;
+ uint8_t radius;
+ int8_t hp;
+ int8_t speed;
+ hh_s_rendering render;
+ //armor/block?
+}hh_entity;
+
+typedef struct {
+ hh_entity p;
+ hh_s_atributes atr;
+}hh_s_player;
+
+
+/// @brief detect for collision enity and eviroment
+/// @param pos1 position of environment tile to be checked
+/// @param pos2 position entity
+/// @return true if collision between enity and environment
+bool hh_collision(vec2 pos1, vec2 pos2);
+
+/// @brief solve collisions
+/// @param environment position
+/// @param entity position
+/// @return solved new entity position
+void hh_solve_collision(vec2 pos_environment, hh_entity* entity);
+
+/// @brief solve collision of entity with background tiles
+/// @param temp_old_entity old data of entity
+/// @param temp_new_entity new data of entity where it wants to go to
+/// @return updated new entity where it actually can go to
+hh_entity hh_background_collision (hh_entity temp_old_entity, hh_entity temp_new_entity);
+
+/// @brief solve collision of player with enemy
+/// @param temp_player data of player
+/// @param temp_enemy data of enemy
+/// @return updated player with new stats if hitted with enemy
+hh_entity hh_enemy_collision(hh_entity temp_player, hh_entity temp_enemy);
+
+/// @brief calculate if circles (entity) hit each other
+/// @param object_1 position of first object (entity)
+/// @param object_2 position of second object (entity)
+/// @param radius_1 radius of first object (entity)
+/// @param radius_2 radius of second object (entity)
+/// @return true if objects collids
+bool hh_distance_circles (vec2 object_1, vec2 object_2, int radius_1, int radius_2);
+
+
diff --git a/src/engine/level.h b/src/engine/level.h
new file mode 100644
index 0000000..8d610dd
--- /dev/null
+++ b/src/engine/level.h
@@ -0,0 +1,5 @@
+#pragma once
+//deal with loading/saving the correct level
+
+/** @brief */
+void hh_map_load();
diff --git a/src/engine/maths.c b/src/engine/maths.c
new file mode 100644
index 0000000..475bba2
--- /dev/null
+++ b/src/engine/maths.c
@@ -0,0 +1,19 @@
+#include "engine/maths.h"
+
+vec2 vec_add(vec2 a, vec2 b){
+ return (vec2){a.x + b.x, a.y + b.y};
+}
+
+vec_cor vec_cen2cor(vec_cen in, vec2 halfDistance){
+ return (vec_cor){
+ .x = in.x - halfDistance.x,
+ .y = in.y - halfDistance.y,
+ };
+}
+
+vec_cen vec_cor2cen(vec_cor in, vec2 halfDistance){
+ return (vec_cen){
+ .x = in.x + halfDistance.x,
+ .y = in.y + halfDistance.y,
+ };
+}
diff --git a/src/engine/maths.h b/src/engine/maths.h
new file mode 100644
index 0000000..bef287e
--- /dev/null
+++ b/src/engine/maths.h
@@ -0,0 +1,22 @@
+#pragma once
+#include <stdint.h>
+// #include <math.h>
+
+typedef struct {
+ int32_t x,y;
+} vec2;
+
+typedef vec2 vec_cen;//centered
+typedef vec2 vec_cor;//left upper corner
+
+vec2 vec_add(vec2 a, vec2 b);
+
+vec_cor vec_cen2cor(vec_cen in, vec2 halfDistance);
+vec_cor vec_cor2cen(vec_cen in, vec2 halfDistance);
+
+//fixed point at decimal 7lsb (world positions in pixels (with fixed decimal point))
+#define HH_MATH_FIXED_POINT 7
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define CLAMP(N,LOWER,UPPER) (MIN(MAX(LOWER, N), UPPER))
diff --git a/src/engine/player_controller.c b/src/engine/player_controller.c
new file mode 100644
index 0000000..647b00c
--- /dev/null
+++ b/src/engine/player_controller.c
@@ -0,0 +1,252 @@
+#include "ppu/types.h"
+#include "engine/camera.h"
+#include "engine/draw_screen.h"
+#include "engine/sprite_controller.h"
+#include "engine/player_controller.h"
+
+#include "input.h"
+
+#include "engine/bullet.h"
+void hh_player_actions() {
+ static Bullet bullet ={
+ .isActive=false,
+ };
+ static hh_entity player={
+ .hp = 4,
+ .speed = 6,
+ .is_grounded = false,
+ .is_hit = false,
+ .radius = 8,
+ .pos = (vec2){32,32},
+ .vel = (vec2){0,0},
+ .vec = (vec2){0,0},
+ .render = {
+ .frame0 = 80,
+ .palette = 3,
+ .fam = (hh_s_ppu_loc_fam_entry){
+ .horizontal_flip = false,
+ .vertical_flip = false,
+ .palette_index = 2,
+ .tilemap_index = 60,
+ }
+ }
+ }, player_new = {0};
+
+
+ static hh_entity enemy={
+ .hp = 4,
+ .speed = 6,
+ .is_grounded = false,
+ .is_hit = false,
+ .radius = 8,
+ .pos = (vec2){128,48},
+ .vel = (vec2){0,0},
+ .vec = (vec2){0,0},
+ .render = {
+ .frame0 = 20,
+ .palette = 7,
+ .fam = (hh_s_ppu_loc_fam_entry){
+ .horizontal_flip = false,
+ .vertical_flip = false,
+ .palette_index = 7,
+ .tilemap_index = 1,
+ }
+ }
+ };
+ player_new = player;
+ // hh_input_read();
+ static uint8_t hit = 0;
+ int8_t hit_timer = 0;
+ int8_t direction_x = (-1 * g_hh_controller_p1.dpad_left) + (1 * g_hh_controller_p1.dpad_right);
+ int8_t direction_y = (-1 * g_hh_controller_p1.dpad_up) + (1 * g_hh_controller_p1.dpad_down);
+
+ if(player.is_hit == true){
+ hit_timer = 9;
+ player.is_hit = false;
+ }
+ if(hit_timer > -10){
+ hit_timer--;
+ }
+
+ if(hit_timer <= 0){
+ if(direction_x != 0){
+ if(player.vel.x > -1 * player.speed && player.vel.x < player.speed) {
+ player.vel.x = player.vel.x + direction_x;
+ } else {
+ if (player.vel.x > 0) {
+ player.vel.x--;
+ } else if(player.vel.x < 0) {
+ player.vel.x++;
+ }
+ }
+ } else {
+ if (player.vel.x > 0) {
+ player.vel.x--;
+ } else if(player.vel.x < 0) {
+ player.vel.x++;
+ }
+ }
+
+ /* // movement Y (w-s) disable gravity to use this
+ if(direction_y != 0){
+ if(player.vel.y > -4 && player.vel.y < 4 ) {
+ player.vel.y = player.vel.y + direction_y;
+ }
+ } else {
+ if (player.vel.y > 0) {
+ player.vel.y--;
+ } else if(player.vel.y < 0) {
+ player.vel.y++;
+ }
+ }
+
+ */
+ } else {
+ if (player.vel.x > 0) {
+ player.vel.x--;
+ } else if(player.vel.x < 0) {
+ player.vel.x++;
+ }
+ player.vel.y++;
+ }
+
+
+ if (g_hh_controller_p1.button_primary && player.is_grounded == true) {//JUMP
+ player.vel.y = -10;
+ player.is_grounded = false;
+ } else if (player.vel.y < 6){
+ player.vel.y += 1; //gravity
+ }
+
+ if(g_hh_controller_p1.button_secondary==true){
+ shootBullet(player.pos,&bullet);
+ }
+ updateBullet(&bullet,5);
+
+
+
+/*
+ player.vel = (vec2){.x = (-1 * g_hh_controller_p1.dpad_left) + (1 * g_hh_controller_p1.dpad_right),
+ .y = (-1 * g_hh_controller_p1.dpad_up) + (1 * g_hh_controller_p1.dpad_down) };
+
+ player_new.vel = (vec2){
+ .x = player.vel.x,
+ .y = player.vel.y,
+ };
+*/
+
+ player_new.vel = (vec2){
+ .x = player.vel.x,
+ .y = player.vel.y,
+ };
+
+ player_new = hh_enemy_collision(player, enemy);
+
+
+ // const int8_t maa = 3;
+ // const int8_t mbb = -3;
+ // if (g_hh_controller_p1.dpad_up)
+ //
+ // if (g_hh_controller_p1.dpad_down)
+ //
+ // if (g_hh_controller_p1.dpad_left) {
+ // player.vel.x += mbb;
+ // // g_hh_demo_balls[0].horizontal_flip = true;
+ // }
+ // if (g_hh_controller_p1.dpad_right) {
+ // player.vel.x += maa;
+ // // g_hh_demo_balls[0].horizontal_flip = true;
+ // }
+ // if (g_hh_controller_p1.button_primary /*&& player.is_grounded*/) //JUMP
+ // player.vel.y += -6;
+ // // // if (g_hh_controller_p1.button_secondary)
+
+ // player.vel.y += 1; //gravity
+
+
+ //END OF VECTOR CHANGES
+ // player.vel.y = CLAMP(player.vel.y,-32,32);
+ // player.vel.x = CLAMP(player.vel.x,-32,32);
+
+ player_new.pos = (vec2){
+ .x = player.pos.x + player_new.vel.x,
+ .y = player.pos.y + player_new.vel.y,
+ };
+
+
+
+ // const uint8_t empty = 0;
+ // hh_s_tiles tiles[9];
+ // const vec2 tile_offset[9] = {
+ // (vec2){-16,-16},(vec2){0,-16},(vec2){+16,-16},
+ // (vec2){-16,0}, (vec2){0,0}, (vec2){+16,0},
+ // (vec2){-16,+16},(vec2){0,+16},(vec2){+16,+16},
+ // };
+ // for (int i = 0; i < 9; i++) {
+ // vec2 temp_pos = vec_add(player.pos, tile_offset[i]);
+ // temp_pos =(vec2){
+ // .x = temp_pos.x,
+ // .y = temp_pos.y,
+ // };
+ // hh_s_tiles tile = {
+ // .pos = temp_pos,
+ // .idx = hh_world_to_tile(temp_pos)
+ // };
+ // if(hh_colidable(tile.idx)) {
+ // tiles[i]=tile;
+ // // printf(" collidable near!");
+ // } else {
+ // tiles[i].idx = 0;
+ // }
+ // }
+ /*
+ 012
+ 345
+ 678
+ */
+ // for (int i = 0; i < 9; i++)
+ // {
+ // if (tiles[i].idx != 0){
+ // hh_solve_collision(tiles[i].pos, &player);
+ // }
+ // }
+
+ player = hh_background_collision ( player, player_new);
+
+ //player = player_new;
+
+ vec_cor cam_pos;//value in tiles
+ // cam_pos = (vec2){0,0};
+ cam_pos = hh_update_camera(player.pos,(vec2){0,0},(vec2){.x=20*16,.y=30*16});//TODO: remove magic number(s)
+ // printf("%i, %i:%i, %i\n",player.pos.x,player.pos.y,cam_pos.x,cam_pos.y);
+ hh_draw_screen(cam_pos);
+ // update player sprite on ppu
+ player.render.fam.position_x = (player.pos.x-cam_pos.x);
+ player.render.fam.position_y = (player.pos.y-cam_pos.y);
+
+ enemy.render.fam.position_x = (enemy.pos.x-cam_pos.x);
+ enemy.render.fam.position_y = (enemy.pos.y-cam_pos.y);
+
+ player.render.fam.tilemap_index = 2;//TODO: these two lines should be redundant
+ player.render.fam.palette_index = 7;
+ // hh_ppu_update_foreground(0, player.render.fam);
+
+ for (int i = 0; i < 4; i++)
+ {
+ hh_s_ppu_loc_fam_entry temp = player.render.fam;
+ temp.position_x = player.render.fam.position_x+(!(player.vel.x>0)?-1:1)*(i%2?8:-8);
+ temp.position_y = player.render.fam.position_y+(i>1?0:-16);
+ temp.tilemap_index = player.render.frame0 + i;
+ temp.palette_index = player.render.palette;
+ temp.horizontal_flip = !(player.vel.x>0);
+ hh_ppu_update_foreground(i,temp);
+ }
+
+
+
+ hh_ppu_update_foreground(4, enemy.render.fam);
+
+}
+
+
+
diff --git a/src/engine/player_controller.h b/src/engine/player_controller.h
new file mode 100644
index 0000000..400c18e
--- /dev/null
+++ b/src/engine/player_controller.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "engine/maths.h"
+#include "engine/entity.h"
+// inputs
+
+void hh_player_actions();
diff --git a/src/engine/sprite_controller.c b/src/engine/sprite_controller.c
new file mode 100644
index 0000000..b38b647
--- /dev/null
+++ b/src/engine/sprite_controller.c
@@ -0,0 +1,24 @@
+#include <stdint.h>
+
+#include "engine/sprite_controller.h"
+#include "ppu/types.h"
+#include "ppu/consts.h"
+#include "ppu/ppu.h"
+
+uint8_t hh_get_palette(uint8_t tile_idx) {
+ return hh_g_sprite_palette[tile_idx];
+}
+
+void hh_setup_palettes(){
+ //TODO: use simpler function
+ for (int idx = 0; idx < HH_PPU_PALETTE_COUNT; idx++) {
+ for (int col = 0; col < HH_PPU_PALETTE_COLOR_COUNT; col++) {
+ hh_ppu_update_color(idx,col,hh_g_palette[idx][col]);
+ }
+ }
+ // hh_ppu_update_palette_table(hh_g_palette);
+}
+
+bool hh_colidable(uint8_t tile_idx){
+ return (hh_get_palette(tile_idx) != 0);
+}
diff --git a/src/engine/sprite_controller.h b/src/engine/sprite_controller.h
new file mode 100644
index 0000000..fc6d3d3
--- /dev/null
+++ b/src/engine/sprite_controller.h
@@ -0,0 +1,118 @@
+#pragma once
+#include <stdint.h>
+
+#include "ppu/types.h"
+
+// handles sprites
+
+// Bg sprites
+
+// Fg or entity sprites
+
+//TODO: pack data inside of sprite_palette LUT
+//HH_PPU_PALETTE_COUNT
+#define HH_SPRITE_COUNT 80
+#define HH_PAL_IDX_SKY 512
+#define HH_PAL_IDX_BRICK 1
+const static uint8_t hh_g_sprite_palette[HH_SPRITE_COUNT] = {
+ //TODO: make a buffer of 16 no-collider sprites (instead of the current 1)
+ 0,1,1,1,1,1,1,1,1,1, //1+9
+ 1,1,1,1,1,1,1,1,1,1, //6+4
+ 1,1,1,1,1,1,1,1,1, //9
+ 7,7,7,2,7,7,1,2,7,
+ 7,7,7,7, //??
+
+ 7,6,6,6,6,6,6,6, //baskets
+ 7,7,7,7,7,7,7,7,7,7, //shop
+ 7,7,7,7,7, //shop
+ 6,6,6,6,6, //(hi-)score
+
+ 3,3,3,3,3,3, //title_screen icon
+ 6,6,6,6,/*6,6,6,6,6,6, //title_screen large letters
+ 6,6,6,6,*/
+ //other palettes here:
+ // [HH_PAL_IDX_SKY] = 0,
+};
+
+
+const static hh_ppu_loc_palette_table_t hh_g_palette = {
+ {//palette info here
+ {0x1,0x2,0x3},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0}},
+ {//Bricks
+ {0x1,0x2,0x3},//01
+ {0xd,0x8,0xa},//24
+ {0x0,0x0,0x1},//25
+ {0x1,0x1,0x1},//26
+ {0x1,0x1,0x2},//27
+ {0x2,0x2,0x3},//28
+ {0x3,0x4,0x5},//29
+ {0x5,0x1,0x7}},
+ {//slime
+ {0x1,0x2,0x3},
+ {0x1,0x3,0x2},
+ {0x4,0x8,0x3},
+ {0x7,0xa,0x4},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0}},
+ {//player //TODO: use one less color && update player indexed sprites
+ {0x0,0x0,0x0},
+ {0x1,0x1,0x1},
+ {0x4,0x2,0x5},
+ {0x7,0x3,0x7},
+ {0xe,0xe,0xe},
+ {0xe,0xe,0xe}, //elemental
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0}},
+ {
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0}},
+ {//elemental
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0},
+ {0x0,0x0,0x0}},
+ {//white
+ {0x1,0x2,0x3},
+ {0xf,0xf,0xf},
+ {0xf,0xf,0xf},
+ {0xf,0xf,0xf},
+ {0xf,0xf,0xf},
+ {0xf,0xf,0xf},
+ {0xf,0xf,0xf},
+ {0xf,0xf,0xf}},
+ {//Dev palette (7)
+ {0x0,0xf,0xf},
+ {0xf,0xf,0xf},
+ {0xf,0x0,0xf},
+ {0xf,0xf,0x0},
+ {0xf,0x0,0x0},
+ {0x0,0xf,0x0},
+ {0x0,0x0,0xf},
+ {0x0,0x0,0x0}}
+};
+
+void hh_setup_palettes();
+
+/** @brief return palette index that belongs to tilemap index */
+uint8_t hh_get_palette(uint8_t tile_idx);
+
+bool hh_colidable(uint8_t tile_idx);
diff --git a/src/engine/title_screen.c b/src/engine/title_screen.c
new file mode 100644
index 0000000..9c7ed48
--- /dev/null
+++ b/src/engine/title_screen.c
@@ -0,0 +1,93 @@
+#include "ppu/ppu.h"
+#include "ppu/types.h"
+#include "ppu/consts.h"
+
+
+#include "engine/draw_screen.h"
+#include "engine/entity.h"
+
+void hh_init_title_screen(){
+
+ // hh_clear_screen();
+
+ //send data
+ uint8_t idx = 0;
+ const uint8_t tilemap_offset = 59;
+ int tiles_h = HH_PPU_BG_CANVAS_TILES_H;
+ int vp_h = HH_PPU_SCREEN_WIDTH/HH_PPU_SPRITE_WIDTH; //screen_h in tiles
+ int vert_offset = tiles_h*3;
+
+ const uint8_t arr[4][4] = {
+ {0,1,1,0},
+ {2,3,3,2},
+ {4,0,0,4},
+ {5,6,6,5},
+ };
+ int val, counter =0;
+ hh_ppu_update_color(5, 0, (hh_ppu_rgb_color_t) {0x1, 0x1, 0x1});
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ val = arr[i][j];
+
+ hh_s_ppu_loc_bam_entry temp = {
+ .vertical_flip=false, .horizontal_flip = ((j % 4 < 2) ? false : true),
+ .palette_index = (counter == 9 || counter == 10? 5:3), .tilemap_index = (val > 0 ? (tilemap_offset + val) : 0)
+ };
+
+ int vert_pos = tiles_h*i;
+ int x_pos = j;
+ idx = vert_offset + vert_pos + x_pos + vp_h/2-2;
+
+ hh_ppu_update_background(idx,temp);
+ counter++;
+ }
+
+ }
+
+
+ const uint8_t letters_offset = 66;
+ const int _size_hooded = 7, _size_v = 2;
+
+ // char* hh = "hooded";
+ int hooded_lookup[7][2]={
+ {0,1},{0,2},//H
+ {3,4},{3,4},//oo
+ {5,6},{13,9},//de
+ {5,6}//d
+ };
+
+ counter = 8;
+ for (int i = 0; i < _size_hooded; i++) {
+ for (int vert = 1; vert <= _size_v; vert++) {
+ //TODO: move 'H' a few pixels to the right for a more cohesive font spacing
+ hh_ppu_update_foreground(counter++, (hh_s_ppu_loc_fam_entry) {
+ .vertical_flip = false, .horizontal_flip = false,
+ .palette_index = 6, .tilemap_index = letters_offset + hooded_lookup[i][vert-1],
+ .position_x = (16*i + 64+48), .position_y = (16*(vert > 1 ? 0:1)*-1 + 64+8+16 +(i==2 || i==3 ? 6:0))
+ });
+ }
+ }
+
+
+ hh_ppu_update_color(5, 1, (hh_ppu_rgb_color_t) {0xa, 0x3, 0x3});
+ hh_ppu_update_color(5, 2, (hh_ppu_rgb_color_t) {0xc, 0x5, 0x3});
+
+ const int _size_havoc = 6;
+ int lookup_havoc[6][2]={
+ {0,1},{0,2},//H
+ {13,10},{7,8},//av
+ {13,11},{13,12}//oc
+ };
+
+ counter = 8 + (_size_hooded * _size_v);
+ for (int i = 0; i < _size_havoc; i++) {
+ for (int vert = 1; vert <= _size_v; vert++) {
+ //TODO: move 'H' a few pixels to the right for a more cohesive font spacing
+ hh_ppu_update_foreground(counter++, (hh_s_ppu_loc_fam_entry) {
+ .vertical_flip = false, .horizontal_flip = (i > 4 && vert==0 ? 1:0),
+ .palette_index = 5, .tilemap_index = letters_offset + lookup_havoc[i][vert-1],
+ .position_x = (16*i +64+32+8), .position_y = (16*(vert > 1 ? 0:1)*-1 + 64+8+48)
+ });
+ }
+ }
+}
diff --git a/src/engine/title_screen.h b/src/engine/title_screen.h
new file mode 100644
index 0000000..b5eda63
--- /dev/null
+++ b/src/engine/title_screen.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void hh_init_title_screen();