From 71871bb700501f5d5d18a5c52cf025fd54d6ec7d Mon Sep 17 00:00:00 2001 From: James Turk Date: Sun, 23 Apr 2023 02:28:34 -0500 Subject: [PATCH] movement --- games/ocean.p8 | 116 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/games/ocean.p8 b/games/ocean.p8 index 825bf0e..fe0a903 100644 --- a/games/ocean.p8 +++ b/games/ocean.p8 @@ -56,55 +56,135 @@ end function draw_ocean() cls(12) local ocean_anim = {[0]=0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0} - if ocean_wind_x != 0 or ocean_wind_y != 0 then + if ocean_wind_x ~= 0 or ocean_wind_y ~= 0 then for x=0,15 do for y=0,15 do local anim = ocean_anim[(flr(time()*4) - ocean_wind_y*y - ocean_wind_x*x) % #ocean_anim] local base = 0 - if ocean_wind_y != 0 then base = 5 end + if ocean_wind_y ~= 0 then base = 5 end if anim > 0 then spr(base+anim, 8*x, 8*y, 1, 1, ocean_wind_x < 0, ocean_wind_y < 0) end end end end + map(player_x-8, player_y-8, 0, 0, 16, 16) + -- DEBUG + print("player: "..player_x..", "..player_y.." heading: "..player_heading) print("wind: "..ocean_wind_x..", "..ocean_wind_y) - draw_ship(player_ship, 64, 64) + draw_ship(player_ship, player_heading, 64, 64) end function update_ocean() if btn(0) then - ocean_wind_x = -1 + player_vx = -1 + player_heading = "W" elseif btn(1) then - ocean_wind_x = 1 + player_vx = 1 + player_heading = "E" else - ocean_wind_x = 0 + player_vx = 0 end if btn(2) then - ocean_wind_y = -1 + player_vy = -1 + player_heading = "N" elseif btn(3) then - ocean_wind_y = 1 + player_vy = 1 + player_heading = "S" else - ocean_wind_y = 0 + player_vy = 0 + end + + if t() - last_move_time > 1 and (player_vy or player_vx) then + last_move_time = t() + player_x += player_vx + player_y += player_vy end end _scenes.ocean = {start=start_ocean, draw=draw_ocean, update=update_ocean} -function draw_ship(ship, x, y) - spr(ship.n, x-ship.w*4, y-ship.h*4, 1, ship.h) - if ship.w > 1 then - spr(ship.n, x-ship.w*4+8, y-ship.h*4, 1, ship.h, true) +function draw_ship(ship, heading, x, y) + local angle = false + if heading == "N" then + angle = 0 + elseif heading == "S" then + angle = 180 end + + spr_r(ship.i, ship.j, x-ship.w/2, y-ship.h/2, ship.w*8, ship.h*8, false, false, ship.w*4, ship.h*4, angle, 0) + if ship.w > 1 then + spr(ship.n, x-ship.w*4+8, y-ship.h*4, 1, ship.h, true, flipy) + end + --function spr_r(i, j, x, y, w, h, flip_x, flip_y, pivot_x, pivot_y, angle, transparent_color) end +-- globals ship_type = { - small={n=64, w=1, h=1}, - medium={n=65, w=1, h=2}, - large={n=66, w=2, h=2}, - ghost={n=67, w=2, h=3} + small={i=0, j=32, w=8, h=8, speed=1}, + medium={i=8, j=32, w=8, h=16, speed=0.6}, + large={i=16, j=32, w=16, h=16, speed=0.4}, + ghost={i=24, j=32, w=126, h=24} } -player_ship = ship_type.ghost +player_ship = ship_type.small +player_x = 20 +player_y = 20 +player_vx = 0 +player_vy = 0 +player_heading = "N" +last_move_time = 0 + +-- external utils + +-- via https://www.lexaloffle.com/bbs/?pid=52525 +function spr_r(i, j, x, y, w, h, flip_x, flip_y, pivot_x, pivot_y, angle, transparent_color) + -- precompute pixel values from tile indices: sprite source top-left, sprite size + local sx = 8 * i + local sy = 8 * j + local sw = 8 * w + local sh = 8 * h + + -- precompute angle trigonometry + local sa = sin(angle) + local ca = cos(angle) + + -- in the operations below, 0.5 offsets represent pixel "inside" + -- we let PICO-8 functions floor coordinates at the last moment for more symmetrical results + + -- precompute "target disc": where we must draw pixels of the rotated sprite (relative to (x, y)) + -- the target disc ratio is the distance between the pivot the farthest corner of the sprite rectangle + local max_dx = max(pivot_x, sw - pivot_x) - 0.5 + local max_dy = max(pivot_y, sh - pivot_y) - 0.5 + local max_sqr_dist = max_dx * max_dx + max_dy * max_dy + local max_dist_minus_half = ceil(sqrt(max_sqr_dist)) - 0.5 + + -- iterate over disc's bounding box, then check if pixel is really in disc + for dx = - max_dist_minus_half, max_dist_minus_half do + for dy = - max_dist_minus_half, max_dist_minus_half do + if dx * dx + dy * dy <= max_sqr_dist then + -- prepare flip factors + local sign_x = flip_x and -1 or 1 + local sign_y = flip_y and -1 or 1 + + local xx = pivot_x + sign_x * ( ca * dx + sa * dy) + local yy = pivot_y + sign_y * (-sa * dx + ca * dy) + + -- make sure to never draw pixels from the spritesheet + -- that are outside the source sprite + if xx >= 0 and xx < sw and yy >= 0 and yy < sh then + -- get source pixel + local c = sget(sx + xx, sy + yy) + -- ignore if transparent color + if c ~= transparent_color then + -- set target pixel color to source pixel color + pset(x + dx, y + dy, c) + end + end + end + end + end + end + __gfx__ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc7cccccccccc7ccc333333333333333333333333555555555555555555555555