Organize project
This commit is contained in:
parent
d6143951d8
commit
6993054d63
7 changed files with 368 additions and 327 deletions
58
src/animation.odin
Normal file
58
src/animation.odin
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
Animation :: struct {
|
||||||
|
texture: rl.Texture2D,
|
||||||
|
num_frames: int,
|
||||||
|
frame_timer: f32,
|
||||||
|
current_frame: int,
|
||||||
|
frame_length: f32,
|
||||||
|
flip: bool,
|
||||||
|
loop: bool,
|
||||||
|
done: bool,
|
||||||
|
offset: rl.Vector2,
|
||||||
|
}
|
||||||
|
|
||||||
|
update_animation :: proc(a: ^Animation) {
|
||||||
|
a.frame_timer += rl.GetFrameTime()
|
||||||
|
|
||||||
|
if a.frame_timer > a.frame_length && !a.done {
|
||||||
|
a.current_frame += 1
|
||||||
|
a.frame_timer = 0
|
||||||
|
|
||||||
|
if a.current_frame == a.num_frames {
|
||||||
|
if a.loop {
|
||||||
|
a.current_frame = 0
|
||||||
|
} else {
|
||||||
|
a.current_frame += -1
|
||||||
|
a.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_animation :: proc(a: Animation, pos: rl.Vector2) {
|
||||||
|
width := f32(a.texture.width)
|
||||||
|
height := f32(a.texture.height)
|
||||||
|
|
||||||
|
source := rl.Rectangle {
|
||||||
|
x = f32(a.current_frame) * width / f32(a.num_frames),
|
||||||
|
y = 0,
|
||||||
|
width = width / f32(a.num_frames),
|
||||||
|
height = height,
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.flip {
|
||||||
|
source.width = -source.width
|
||||||
|
}
|
||||||
|
|
||||||
|
dest := rl.Rectangle {
|
||||||
|
x = pos.x + a.offset.x,
|
||||||
|
y = pos.y + a.offset.y,
|
||||||
|
width = width / f32(a.num_frames),
|
||||||
|
height = height,
|
||||||
|
}
|
||||||
|
|
||||||
|
rl.DrawTexturePro(a.texture, source, dest, {dest.width / 2, dest.height}, 0, rl.WHITE)
|
||||||
|
}
|
||||||
5
src/constants.odin
Normal file
5
src/constants.odin
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
GAME_SCREEN_WIDTH: f32 = 480
|
||||||
|
GAME_SCREEN_HEIGHT: f32 = 270
|
||||||
|
TILE_SIZE :: 16
|
||||||
144
src/entity.odin
Normal file
144
src/entity.odin
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import "core:math"
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
EntityKind :: enum {
|
||||||
|
Player,
|
||||||
|
Tile,
|
||||||
|
Item,
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerData :: struct {
|
||||||
|
animation: Animation,
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemData :: struct {
|
||||||
|
id: int,
|
||||||
|
count: int,
|
||||||
|
texture: rl.Texture2D,
|
||||||
|
}
|
||||||
|
|
||||||
|
TileData :: struct {
|
||||||
|
has_plant: bool,
|
||||||
|
is_watered: bool,
|
||||||
|
plant_id: int,
|
||||||
|
animation: Animation,
|
||||||
|
plant_grown: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityData :: union {
|
||||||
|
PlayerData,
|
||||||
|
TileData,
|
||||||
|
ItemData,
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity :: struct {
|
||||||
|
pos: rl.Vector2,
|
||||||
|
kind: EntityKind,
|
||||||
|
handle: EntityHandle,
|
||||||
|
flags: bit_set[EntityFlags],
|
||||||
|
data: EntityData,
|
||||||
|
}
|
||||||
|
latest_entity_handle: int
|
||||||
|
|
||||||
|
EntityHandle :: int
|
||||||
|
EntityFlags :: enum {
|
||||||
|
nil,
|
||||||
|
Allocated,
|
||||||
|
}
|
||||||
|
|
||||||
|
create_entity :: proc(entity: Entity) -> ^Entity {
|
||||||
|
for &e in entities {
|
||||||
|
if .Allocated not_in e.flags {
|
||||||
|
e = entity
|
||||||
|
e.flags = {.Allocated}
|
||||||
|
latest_entity_handle += 1
|
||||||
|
return &e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(false, "Failed to allocate entity, not enough space!!!!")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_entity :: proc(e: ^Entity) {
|
||||||
|
e^ = Entity{}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_to_entity :: proc(handle: EntityHandle) -> ^Entity {
|
||||||
|
for &e in entities {
|
||||||
|
if handle == e.handle && .Allocated in e.flags {
|
||||||
|
return &e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
update_entities :: proc() {
|
||||||
|
for &e in entities {
|
||||||
|
if .Allocated not_in e.flags {continue}
|
||||||
|
|
||||||
|
#partial switch &data in e.data {
|
||||||
|
case TileData:
|
||||||
|
update_tile(e, &data)
|
||||||
|
case PlayerData:
|
||||||
|
update_animation(&data.animation)
|
||||||
|
case ItemData:
|
||||||
|
//rl.DrawTextureV(data.texture, e.pos + {0, t * 3}, rl.WHITE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_tile :: proc(e: Entity, data: ^TileData) {
|
||||||
|
update_animation(&data.animation)
|
||||||
|
if data.has_plant && data.animation.done && data.plant_grown == false {
|
||||||
|
data.plant_grown = true
|
||||||
|
data.has_plant = false
|
||||||
|
rl.PlaySound(pickup_sound)
|
||||||
|
item := create_entity(
|
||||||
|
Entity {
|
||||||
|
pos = e.pos,
|
||||||
|
kind = .Item,
|
||||||
|
data = ItemData{id = data.plant_id, count = 3, texture = tomato_texture},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_entities :: proc() {
|
||||||
|
for e in entities {
|
||||||
|
if .Allocated not_in e.flags {continue}
|
||||||
|
|
||||||
|
switch &data in e.data {
|
||||||
|
case TileData:
|
||||||
|
draw_tile(e)
|
||||||
|
case PlayerData:
|
||||||
|
draw_player(e)
|
||||||
|
case ItemData:
|
||||||
|
draw_item(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_to_handle :: proc(e: Entity) -> EntityHandle {
|
||||||
|
return e.handle
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_player :: proc(e: Entity) {
|
||||||
|
data, ok := e.data.(PlayerData)
|
||||||
|
draw_animation(data.animation, e.pos)
|
||||||
|
}
|
||||||
|
draw_tile :: proc(e: Entity) {
|
||||||
|
data, ok := e.data.(TileData)
|
||||||
|
//rl.DrawRectangle(auto_cast e.pos.x, auto_cast e.pos.y, TILE_SIZE, TILE_SIZE, rl.BLACK)
|
||||||
|
rl.DrawTextureV(tile_dirt_dry_texture, e.pos, rl.WHITE)
|
||||||
|
if data.has_plant {
|
||||||
|
draw_animation(data.animation, e.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_item :: proc(e: Entity) {
|
||||||
|
data, ok := e.data.(ItemData)
|
||||||
|
t := f32(math.sin(rl.GetTime() * 5))
|
||||||
|
rl.DrawTextureV(data.texture, e.pos + {0, t * 3}, rl.WHITE)
|
||||||
|
//draw_animation(data.animation, e.pos + {0, t * 3})
|
||||||
|
}
|
||||||
29
src/globals.odin
Normal file
29
src/globals.odin
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import t "../tween"
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
SELL_BUTTON_POS :: rl.Vector2{432, 16}
|
||||||
|
|
||||||
|
game_camera := rl.Camera2D {
|
||||||
|
zoom = 1,
|
||||||
|
}
|
||||||
|
ui_camera := rl.Camera2D {
|
||||||
|
zoom = 1,
|
||||||
|
}
|
||||||
|
game_render_buffer: rl.RenderTexture2D
|
||||||
|
screen_game_area: rl.Rectangle
|
||||||
|
game_render_buffer_area := rl.Rectangle{0, 0, GAME_SCREEN_WIDTH, -GAME_SCREEN_HEIGHT}
|
||||||
|
screen_scale: f32
|
||||||
|
|
||||||
|
world_mouse: rl.Vector2
|
||||||
|
|
||||||
|
player_handle: EntityHandle
|
||||||
|
|
||||||
|
tiles: [dynamic]Tile
|
||||||
|
animations: [dynamic]^Animation
|
||||||
|
|
||||||
|
entities: [256]Entity
|
||||||
|
|
||||||
|
tween_ctx_f32: t.TweenContext(f32)
|
||||||
|
tween_ctx_vec2: t.TweenContext([2]f32)
|
||||||
382
src/main.odin
382
src/main.odin
|
|
@ -8,75 +8,11 @@ import "core:math/linalg"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
GAME_SCREEN_WIDTH: f32 = 480
|
|
||||||
GAME_SCREEN_HEIGHT: f32 = 270
|
|
||||||
|
|
||||||
SELL_BUTTON_POS :: rl.Vector2{432, 16}
|
|
||||||
|
|
||||||
TILE_SIZE :: 16
|
|
||||||
game_render_buffer: rl.RenderTexture2D
|
|
||||||
game_camera := rl.Camera2D {
|
|
||||||
zoom = 1,
|
|
||||||
}
|
|
||||||
ui_camera := rl.Camera2D {
|
|
||||||
zoom = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
screen_scale: f32
|
|
||||||
world_mouse: rl.Vector2
|
|
||||||
screen_game_area: rl.Rectangle
|
|
||||||
game_render_buffer_area := rl.Rectangle{0, 0, GAME_SCREEN_WIDTH, -GAME_SCREEN_HEIGHT}
|
|
||||||
|
|
||||||
pickup_sound: rl.Sound
|
|
||||||
pickup_sound_data: []u8 : #load("../assets/sounds/pickup_sound.mp3")
|
|
||||||
|
|
||||||
player_spritesheet_sprite: []u8 : #load("../assets/player.png")
|
|
||||||
tomato_spritesheet_sprite: []u8 : #load("../assets/tomato.png")
|
|
||||||
tomato_item_sprite: []u8 : #load("../assets/tomato_item.png")
|
|
||||||
sell_button_sprite: []u8 : #load("../assets/sell_button.png")
|
|
||||||
background_sprite: []u8 : #load("../assets/background.png")
|
|
||||||
tile_dirt_dry_sprite: []u8 : #load("../assets/tile_dirt_dry.png")
|
|
||||||
tile_dirt_wet_sprite: []u8 : #load("../assets/tile_dirt_wet.png")
|
|
||||||
|
|
||||||
load_texture_from_memory :: proc(data: []u8) -> (texture: rl.Texture2D) {
|
|
||||||
img := rl.LoadImageFromMemory(".png", raw_data(data), auto_cast len(data))
|
|
||||||
defer rl.UnloadImage(img)
|
|
||||||
texture = rl.LoadTextureFromImage(img)
|
|
||||||
return texture
|
|
||||||
}
|
|
||||||
|
|
||||||
load_sound_from_memory :: proc(
|
|
||||||
data: []u8,
|
|
||||||
sound_extension: cstring = ".mp3",
|
|
||||||
) -> (
|
|
||||||
sound: rl.Sound,
|
|
||||||
) {
|
|
||||||
wav := rl.LoadWaveFromMemory(sound_extension, raw_data(data), auto_cast len(data))
|
|
||||||
defer rl.UnloadWave(wav)
|
|
||||||
sound = rl.LoadSoundFromWave(wav)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sell_button_texture: rl.Texture2D
|
|
||||||
background_texture: rl.Texture2D
|
|
||||||
tile_dirt_dry_texture: rl.Texture2D
|
|
||||||
tile_dirt_wet_texture: rl.Texture2D
|
|
||||||
tomato_texture: rl.Texture2D
|
|
||||||
|
|
||||||
player_animation: Animation
|
|
||||||
tomato_animation: Animation
|
|
||||||
|
|
||||||
player_handle: EntityHandle
|
|
||||||
|
|
||||||
tiles: [dynamic]Tile
|
|
||||||
animations: [dynamic]^Animation
|
|
||||||
|
|
||||||
entities: [256]Entity
|
|
||||||
|
|
||||||
tween_ctx_f32: t.TweenContext(f32)
|
|
||||||
tween_ctx_vec2: t.TweenContext([2]f32)
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
run()
|
||||||
|
}
|
||||||
|
|
||||||
|
run :: proc() {
|
||||||
rl.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE, .MSAA_4X_HINT})
|
rl.SetConfigFlags({.VSYNC_HINT, .WINDOW_RESIZABLE, .MSAA_4X_HINT})
|
||||||
rl.InitWindow(1280, 720, "Raylib Minimal")
|
rl.InitWindow(1280, 720, "Raylib Minimal")
|
||||||
rl.SetTargetFPS(rl.GetMonitorRefreshRate(rl.GetCurrentMonitor()))
|
rl.SetTargetFPS(rl.GetMonitorRefreshRate(rl.GetCurrentMonitor()))
|
||||||
|
|
@ -88,57 +24,17 @@ main :: proc() {
|
||||||
fmt.println("Audio borked!")
|
fmt.println("Audio borked!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pickup_sound = load_sound_from_memory(pickup_sound_data)
|
load_resources()
|
||||||
|
rl.SetSoundVolume(pickup_sound, 0.1)
|
||||||
game_render_buffer = rl.LoadRenderTexture(
|
|
||||||
auto_cast GAME_SCREEN_WIDTH,
|
|
||||||
auto_cast GAME_SCREEN_HEIGHT,
|
|
||||||
)
|
|
||||||
rl.SetTextureFilter(game_render_buffer.texture, rl.TextureFilter.POINT) // Texture scale filter to use
|
|
||||||
|
|
||||||
tween_ctx_f32 = t.context_init(f32)
|
|
||||||
tween_ctx_vec2 = t.context_init([2]f32)
|
|
||||||
defer t.context_destroy(tween_ctx_f32)
|
|
||||||
defer t.context_destroy(tween_ctx_vec2)
|
|
||||||
|
|
||||||
player_animation = Animation {
|
|
||||||
texture = load_texture_from_memory(player_spritesheet_sprite),
|
|
||||||
num_frames = 2,
|
|
||||||
frame_length = 0.5,
|
|
||||||
loop = true,
|
|
||||||
}
|
|
||||||
tomato_animation = Animation {
|
|
||||||
texture = load_texture_from_memory(tomato_spritesheet_sprite),
|
|
||||||
num_frames = 4,
|
|
||||||
frame_length = 0.1,
|
|
||||||
loop = false,
|
|
||||||
offset = {TILE_SIZE / 2, TILE_SIZE},
|
|
||||||
}
|
|
||||||
tomato_texture = load_texture_from_memory(tomato_item_sprite)
|
|
||||||
sell_button_texture = load_texture_from_memory(sell_button_sprite)
|
|
||||||
background_texture = load_texture_from_memory(background_sprite)
|
|
||||||
tile_dirt_dry_texture = load_texture_from_memory(tile_dirt_dry_sprite)
|
|
||||||
tile_dirt_wet_texture = load_texture_from_memory(tile_dirt_wet_sprite)
|
|
||||||
|
|
||||||
e := create_entity(
|
|
||||||
Entity {
|
|
||||||
pos = {GAME_SCREEN_WIDTH / 2, GAME_SCREEN_HEIGHT / 2},
|
|
||||||
kind = .Player,
|
|
||||||
data = PlayerData{animation = player_animation},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
player_handle = entity_to_handle(e^)
|
|
||||||
|
|
||||||
rl.PlaySound(pickup_sound)
|
rl.PlaySound(pickup_sound)
|
||||||
|
|
||||||
if true {for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
free_all(context.temp_allocator)
|
free_all(context.temp_allocator)
|
||||||
update()
|
update()
|
||||||
draw()
|
draw()
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
rl.UnloadRenderTexture(game_render_buffer) // Unload render texture
|
|
||||||
|
free_resources()
|
||||||
rl.CloseAudioDevice()
|
rl.CloseAudioDevice()
|
||||||
rl.CloseWindow()
|
rl.CloseWindow()
|
||||||
}
|
}
|
||||||
|
|
@ -232,227 +128,59 @@ draw :: proc() {
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation :: struct {
|
load_resources :: proc() {
|
||||||
texture: rl.Texture2D,
|
tween_ctx_f32 = t.context_init(f32)
|
||||||
num_frames: int,
|
tween_ctx_vec2 = t.context_init([2]f32)
|
||||||
frame_timer: f32,
|
|
||||||
current_frame: int,
|
|
||||||
frame_length: f32,
|
|
||||||
flip: bool,
|
|
||||||
loop: bool,
|
|
||||||
done: bool,
|
|
||||||
offset: rl.Vector2,
|
|
||||||
}
|
|
||||||
|
|
||||||
update_animation :: proc(a: ^Animation) {
|
game_render_buffer = rl.LoadRenderTexture(
|
||||||
a.frame_timer += rl.GetFrameTime()
|
auto_cast GAME_SCREEN_WIDTH,
|
||||||
|
auto_cast GAME_SCREEN_HEIGHT,
|
||||||
|
)
|
||||||
|
rl.SetTextureFilter(game_render_buffer.texture, rl.TextureFilter.POINT) // Texture scale filter to use
|
||||||
|
|
||||||
if a.frame_timer > a.frame_length && !a.done {
|
player_animation = Animation {
|
||||||
a.current_frame += 1
|
texture = load_texture_from_memory(player_spritesheet_sprite),
|
||||||
a.frame_timer = 0
|
num_frames = 2,
|
||||||
|
frame_length = 0.5,
|
||||||
if a.current_frame == a.num_frames {
|
loop = true,
|
||||||
if a.loop {
|
|
||||||
a.current_frame = 0
|
|
||||||
} else {
|
|
||||||
a.current_frame += -1
|
|
||||||
a.done = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
tomato_animation = Animation {
|
||||||
|
texture = load_texture_from_memory(tomato_spritesheet_sprite),
|
||||||
draw_animation :: proc(a: Animation, pos: rl.Vector2) {
|
num_frames = 4,
|
||||||
width := f32(a.texture.width)
|
frame_length = 0.1,
|
||||||
height := f32(a.texture.height)
|
loop = false,
|
||||||
|
offset = {TILE_SIZE / 2, TILE_SIZE},
|
||||||
source := rl.Rectangle {
|
|
||||||
x = f32(a.current_frame) * width / f32(a.num_frames),
|
|
||||||
y = 0,
|
|
||||||
width = width / f32(a.num_frames),
|
|
||||||
height = height,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.flip {
|
tomato_texture = load_texture_from_memory(tomato_item_sprite)
|
||||||
source.width = -source.width
|
sell_button_texture = load_texture_from_memory(sell_button_sprite)
|
||||||
}
|
background_texture = load_texture_from_memory(background_sprite)
|
||||||
|
tile_dirt_dry_texture = load_texture_from_memory(tile_dirt_dry_sprite)
|
||||||
|
tile_dirt_wet_texture = load_texture_from_memory(tile_dirt_wet_sprite)
|
||||||
|
pickup_sound = load_sound_from_memory(pickup_sound_data)
|
||||||
|
|
||||||
dest := rl.Rectangle {
|
|
||||||
x = pos.x + a.offset.x,
|
|
||||||
y = pos.y + a.offset.y,
|
|
||||||
width = width / f32(a.num_frames),
|
|
||||||
height = height,
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.DrawTexturePro(a.texture, source, dest, {dest.width / 2, dest.height}, 0, rl.WHITE)
|
e := create_entity(
|
||||||
|
Entity {
|
||||||
|
pos = {GAME_SCREEN_WIDTH / 2, GAME_SCREEN_HEIGHT / 2},
|
||||||
|
kind = .Player,
|
||||||
|
data = PlayerData{animation = player_animation},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
player_handle = entity_to_handle(e^)
|
||||||
}
|
}
|
||||||
|
|
||||||
Tile :: struct {
|
free_resources :: proc() {
|
||||||
id: int,
|
t.context_destroy(tween_ctx_f32)
|
||||||
pos: rl.Vector2,
|
t.context_destroy(tween_ctx_vec2)
|
||||||
animation: Animation,
|
|
||||||
}
|
|
||||||
|
|
||||||
spawn_tile_under_mouse :: proc() {
|
rl.UnloadSound(pickup_sound)
|
||||||
tile_position := get_tile_position(world_mouse)
|
|
||||||
old_tile: bool
|
|
||||||
for e in entities {
|
|
||||||
if .Allocated not_in e.flags {continue}
|
|
||||||
if e.kind == .Tile && e.pos == tile_position {
|
|
||||||
old_tile = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !old_tile {
|
|
||||||
create_entity(
|
|
||||||
Entity {
|
|
||||||
pos = tile_position,
|
|
||||||
kind = .Tile,
|
|
||||||
data = TileData{has_plant = true, plant_id = 0, animation = tomato_animation},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_tile_position :: proc(wpos: rl.Vector2) -> rl.Vector2 {
|
rl.UnloadTexture(tomato_texture)
|
||||||
return {math.floor(wpos.x / TILE_SIZE) * TILE_SIZE, math.floor(wpos.y / TILE_SIZE) * TILE_SIZE}
|
rl.UnloadTexture(sell_button_texture)
|
||||||
}
|
rl.UnloadTexture(background_texture)
|
||||||
|
rl.UnloadTexture(tile_dirt_dry_texture)
|
||||||
|
rl.UnloadTexture(tile_dirt_wet_texture)
|
||||||
|
|
||||||
EntityKind :: enum {
|
rl.UnloadRenderTexture(game_render_buffer) // Unload render texture
|
||||||
Player,
|
|
||||||
Tile,
|
|
||||||
Item,
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerData :: struct {
|
|
||||||
animation: Animation,
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemData :: struct {
|
|
||||||
id: int,
|
|
||||||
count: int,
|
|
||||||
texture: rl.Texture2D,
|
|
||||||
}
|
|
||||||
|
|
||||||
TileData :: struct {
|
|
||||||
has_plant: bool,
|
|
||||||
is_watered: bool,
|
|
||||||
plant_id: int,
|
|
||||||
animation: Animation,
|
|
||||||
plant_grown: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityData :: union {
|
|
||||||
PlayerData,
|
|
||||||
TileData,
|
|
||||||
ItemData,
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity :: struct {
|
|
||||||
pos: rl.Vector2,
|
|
||||||
kind: EntityKind,
|
|
||||||
handle: EntityHandle,
|
|
||||||
flags: bit_set[EntityFlags],
|
|
||||||
data: EntityData,
|
|
||||||
}
|
|
||||||
latest_entity_handle: int
|
|
||||||
|
|
||||||
EntityHandle :: int
|
|
||||||
EntityFlags :: enum {
|
|
||||||
nil,
|
|
||||||
Allocated,
|
|
||||||
}
|
|
||||||
|
|
||||||
create_entity :: proc(entity: Entity) -> ^Entity {
|
|
||||||
for &e in entities {
|
|
||||||
if .Allocated not_in e.flags {
|
|
||||||
e = entity
|
|
||||||
e.flags = {.Allocated}
|
|
||||||
latest_entity_handle += 1
|
|
||||||
return &e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(false, "Failed to allocate entity, not enough space!!!!")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy_entity :: proc(e: ^Entity) {
|
|
||||||
e^ = Entity{}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_to_entity :: proc(handle: EntityHandle) -> ^Entity {
|
|
||||||
for &e in entities {
|
|
||||||
if handle == e.handle && .Allocated in e.flags {
|
|
||||||
return &e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
update_entities :: proc() {
|
|
||||||
for &e in entities {
|
|
||||||
if .Allocated not_in e.flags {continue}
|
|
||||||
|
|
||||||
#partial switch &data in e.data {
|
|
||||||
case TileData:
|
|
||||||
update_tile(e, &data)
|
|
||||||
case PlayerData:
|
|
||||||
update_animation(&data.animation)
|
|
||||||
case ItemData:
|
|
||||||
//rl.DrawTextureV(data.texture, e.pos + {0, t * 3}, rl.WHITE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_tile :: proc(e: Entity, data: ^TileData) {
|
|
||||||
update_animation(&data.animation)
|
|
||||||
if data.has_plant && data.animation.done && data.plant_grown == false {
|
|
||||||
data.plant_grown = true
|
|
||||||
data.has_plant = false
|
|
||||||
rl.PlaySound(pickup_sound)
|
|
||||||
item := create_entity(
|
|
||||||
Entity {
|
|
||||||
pos = e.pos,
|
|
||||||
kind = .Item,
|
|
||||||
data = ItemData{id = data.plant_id, count = 3, texture = tomato_texture},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_entities :: proc() {
|
|
||||||
for e in entities {
|
|
||||||
if .Allocated not_in e.flags {continue}
|
|
||||||
|
|
||||||
switch &data in e.data {
|
|
||||||
case TileData:
|
|
||||||
draw_tile(e)
|
|
||||||
case PlayerData:
|
|
||||||
draw_player(e)
|
|
||||||
case ItemData:
|
|
||||||
draw_item(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entity_to_handle :: proc(e: Entity) -> EntityHandle {
|
|
||||||
return e.handle
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_player :: proc(e: Entity) {
|
|
||||||
data, ok := e.data.(PlayerData)
|
|
||||||
draw_animation(data.animation, e.pos)
|
|
||||||
}
|
|
||||||
draw_tile :: proc(e: Entity) {
|
|
||||||
data, ok := e.data.(TileData)
|
|
||||||
//rl.DrawRectangle(auto_cast e.pos.x, auto_cast e.pos.y, TILE_SIZE, TILE_SIZE, rl.BLACK)
|
|
||||||
rl.DrawTextureV(tile_dirt_dry_texture, e.pos, rl.WHITE)
|
|
||||||
if data.has_plant {
|
|
||||||
draw_animation(data.animation, e.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
draw_item :: proc(e: Entity) {
|
|
||||||
data, ok := e.data.(ItemData)
|
|
||||||
t := f32(math.sin(rl.GetTime() * 5))
|
|
||||||
rl.DrawTextureV(data.texture, e.pos + {0, t * 3}, rl.WHITE)
|
|
||||||
//draw_animation(data.animation, e.pos + {0, t * 3})
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
43
src/resources.odin
Normal file
43
src/resources.odin
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
pickup_sound_data: []u8 : #load("../assets/sounds/pickup_sound.mp3")
|
||||||
|
|
||||||
|
player_spritesheet_sprite: []u8 : #load("../assets/player.png")
|
||||||
|
tomato_spritesheet_sprite: []u8 : #load("../assets/tomato.png")
|
||||||
|
tomato_item_sprite: []u8 : #load("../assets/tomato_item.png")
|
||||||
|
sell_button_sprite: []u8 : #load("../assets/sell_button.png")
|
||||||
|
background_sprite: []u8 : #load("../assets/background.png")
|
||||||
|
tile_dirt_dry_sprite: []u8 : #load("../assets/tile_dirt_dry.png")
|
||||||
|
tile_dirt_wet_sprite: []u8 : #load("../assets/tile_dirt_wet.png")
|
||||||
|
|
||||||
|
load_texture_from_memory :: proc(data: []u8) -> (texture: rl.Texture2D) {
|
||||||
|
img := rl.LoadImageFromMemory(".png", raw_data(data), auto_cast len(data))
|
||||||
|
defer rl.UnloadImage(img)
|
||||||
|
texture = rl.LoadTextureFromImage(img)
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
|
||||||
|
load_sound_from_memory :: proc(
|
||||||
|
data: []u8,
|
||||||
|
sound_extension: cstring = ".mp3",
|
||||||
|
) -> (
|
||||||
|
sound: rl.Sound,
|
||||||
|
) {
|
||||||
|
wav := rl.LoadWaveFromMemory(sound_extension, raw_data(data), auto_cast len(data))
|
||||||
|
defer rl.UnloadWave(wav)
|
||||||
|
sound = rl.LoadSoundFromWave(wav)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pickup_sound: rl.Sound
|
||||||
|
|
||||||
|
sell_button_texture: rl.Texture2D
|
||||||
|
background_texture: rl.Texture2D
|
||||||
|
tile_dirt_dry_texture: rl.Texture2D
|
||||||
|
tile_dirt_wet_texture: rl.Texture2D
|
||||||
|
tomato_texture: rl.Texture2D
|
||||||
|
|
||||||
|
player_animation: Animation
|
||||||
|
tomato_animation: Animation
|
||||||
34
src/tile.odin
Normal file
34
src/tile.odin
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import "core:math"
|
||||||
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
Tile :: struct {
|
||||||
|
id: int,
|
||||||
|
pos: rl.Vector2,
|
||||||
|
animation: Animation,
|
||||||
|
}
|
||||||
|
|
||||||
|
spawn_tile_under_mouse :: proc() {
|
||||||
|
tile_position := get_tile_position(world_mouse)
|
||||||
|
old_tile: bool
|
||||||
|
for e in entities {
|
||||||
|
if .Allocated not_in e.flags {continue}
|
||||||
|
if e.kind == .Tile && e.pos == tile_position {
|
||||||
|
old_tile = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !old_tile {
|
||||||
|
create_entity(
|
||||||
|
Entity {
|
||||||
|
pos = tile_position,
|
||||||
|
kind = .Tile,
|
||||||
|
data = TileData{has_plant = true, plant_id = 0, animation = tomato_animation},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get_tile_position :: proc(wpos: rl.Vector2) -> rl.Vector2 {
|
||||||
|
return {math.floor(wpos.x / TILE_SIZE) * TILE_SIZE, math.floor(wpos.y / TILE_SIZE) * TILE_SIZE}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue