Added y sorting and refactoring
This commit is contained in:
parent
9504812ed5
commit
692c066a1a
9 changed files with 209 additions and 51 deletions
2
Makefile
2
Makefile
|
|
@ -1,5 +1,5 @@
|
|||
run:
|
||||
odin run src -out:game.exe -debug -use-separate-modules -vet
|
||||
odin run src -out:game.exe -debug -vet
|
||||
|
||||
build:
|
||||
odin build src -out:game.exe -debug -use-separate-modules
|
||||
|
|
|
|||
Binary file not shown.
BIN
assets/axe.png
Normal file
BIN
assets/axe.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 212 B |
BIN
assets/watering_can.png
Normal file
BIN
assets/watering_can.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 431 B |
|
|
@ -3,3 +3,5 @@ package game
|
|||
GAME_SCREEN_WIDTH: f32 = 480
|
||||
GAME_SCREEN_HEIGHT: f32 = 270
|
||||
TILE_SIZE :: 16
|
||||
|
||||
PICKUP_DISTANCE :: 15
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package game
|
||||
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:math/linalg"
|
||||
import "core:slice"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
EntityKind :: enum {
|
||||
|
|
@ -50,20 +53,26 @@ EntityFlags :: enum {
|
|||
}
|
||||
|
||||
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
|
||||
entity := entity
|
||||
entity.flags = {.Allocated}
|
||||
entity.handle = latest_entity_handle
|
||||
latest_entity_handle += 1
|
||||
append(&entities, entity)
|
||||
return &entities[len(entities) - 1]
|
||||
}
|
||||
|
||||
destroy_entity :: proc(e: ^Entity) {
|
||||
e^ = Entity{}
|
||||
destroy_entity_by_handle(e.handle)
|
||||
}
|
||||
|
||||
destroy_entity_by_handle :: proc(handle: EntityHandle) {
|
||||
idx: int
|
||||
for ent, i in entities {
|
||||
if ent.handle == handle {
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
unordered_remove(&entities, idx)
|
||||
}
|
||||
|
||||
handle_to_entity :: proc(handle: EntityHandle) -> ^Entity {
|
||||
|
|
@ -76,6 +85,8 @@ handle_to_entity :: proc(handle: EntityHandle) -> ^Entity {
|
|||
}
|
||||
|
||||
update_entities :: proc() {
|
||||
player_entity, _ := get_player_entity_and_data()
|
||||
|
||||
for &e in entities {
|
||||
if .Allocated not_in e.flags {continue}
|
||||
|
||||
|
|
@ -85,17 +96,50 @@ update_entities :: proc() {
|
|||
case PlayerData:
|
||||
update_animation(&data.animation)
|
||||
case ItemData:
|
||||
//rl.DrawTextureV(data.texture, e.pos + {0, t * 3}, rl.WHITE)
|
||||
dist := linalg.distance(e.pos, player_entity.pos)
|
||||
if dist <= PICKUP_DISTANCE {
|
||||
rl.PlaySound(pickup_sound)
|
||||
player_inventory[data.id] += data.count
|
||||
destroy_entity(&e)
|
||||
}
|
||||
}
|
||||
}
|
||||
init_hotbar_from_inventory()
|
||||
}
|
||||
|
||||
get_player_entity_and_data :: proc() -> (^Entity, PlayerData) {
|
||||
player_entity := handle_to_entity(player_handle)
|
||||
if player_entity == nil {
|
||||
fmt.panicf("Player handle is invalid, how???")
|
||||
}
|
||||
player_data, ok := player_entity.data.(PlayerData);if ok {
|
||||
return player_entity, player_data
|
||||
} else {
|
||||
fmt.panicf("Player data is invalid, how???")
|
||||
}
|
||||
return nil, {}
|
||||
}
|
||||
|
||||
draw_entities :: proc() {
|
||||
slice.sort_by(entities[:], proc(a, b: Entity) -> bool {
|
||||
return a.pos.y < b.pos.y
|
||||
})
|
||||
for e in entities {
|
||||
if .Allocated not_in e.flags {continue}
|
||||
#partial switch &data in e.data {
|
||||
case TileData:
|
||||
draw_tile(e)
|
||||
}
|
||||
}
|
||||
for e in entities {
|
||||
if .Allocated not_in e.flags {continue}
|
||||
|
||||
// Draw debug circle
|
||||
//rl.DrawCircleV(e.pos, 1, rl.RED)
|
||||
|
||||
switch &data in e.data {
|
||||
case TileData:
|
||||
draw_tile(e)
|
||||
draw_tile_plant(e)
|
||||
case PlayerData:
|
||||
draw_player(e)
|
||||
case ItemData:
|
||||
|
|
@ -110,12 +154,16 @@ entity_to_handle :: proc(e: Entity) -> EntityHandle {
|
|||
|
||||
draw_player :: proc(e: Entity) {
|
||||
data, ok := e.data.(PlayerData);if ok {
|
||||
draw_animation(data.animation, e.pos)
|
||||
draw_animation(data.animation, e.pos + {TILE_SIZE, TILE_SIZE})
|
||||
}
|
||||
}
|
||||
|
||||
draw_item :: proc(e: Entity) {
|
||||
data, ok := e.data.(ItemData);if ok {
|
||||
t := f32(math.sin(rl.GetTime() * 5))
|
||||
rl.DrawTextureV(data.texture, e.pos + {0, t * 3}, rl.WHITE)
|
||||
pos := e.pos + {0, t * 3}
|
||||
rl.DrawTextureV(data.texture, pos, rl.WHITE)
|
||||
// Draw debug circle
|
||||
//rl.DrawCircleV(pos, 1, rl.RED)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ player_handle: EntityHandle
|
|||
tiles: [dynamic]Tile
|
||||
animations: [dynamic]^Animation
|
||||
|
||||
entities: [256]Entity
|
||||
entities: [dynamic]Entity
|
||||
|
||||
current_tick: time.Tick
|
||||
|
||||
|
|
@ -33,6 +33,7 @@ tween_ctx_f32: t.TweenContext(f32)
|
|||
tween_ctx_vec2: t.TweenContext([2]f32)
|
||||
|
||||
player_inventory: [InventoryItem]int
|
||||
hotbar: Hotbar
|
||||
|
||||
InventoryItem :: enum {
|
||||
//Tools
|
||||
|
|
@ -48,16 +49,7 @@ InventoryItem :: enum {
|
|||
//Other
|
||||
}
|
||||
|
||||
ITEM_TEXTURES := [InventoryItem]^rl.Texture2D {
|
||||
.hoe = &hoe_texture,
|
||||
.scythe = &scythe_texture,
|
||||
.watering_can = &tomato_texture,
|
||||
.pickaxe = &tomato_texture,
|
||||
.axe = &tomato_texture,
|
||||
.tomato = &tomato_texture,
|
||||
.tomato_seed = &tomato_texture,
|
||||
.tomato_seedling = &tomato_texture,
|
||||
}
|
||||
ITEM_TEXTURES: [InventoryItem]^rl.Texture2D
|
||||
|
||||
HotbarKind :: enum {
|
||||
tools,
|
||||
|
|
@ -66,16 +58,10 @@ HotbarKind :: enum {
|
|||
|
||||
Hotbar :: struct {
|
||||
kind: HotbarKind,
|
||||
tool_slots: []InventoryItem,
|
||||
seed_slots: []InventoryItem,
|
||||
tool_slots: [dynamic]InventoryItem,
|
||||
seed_slots: [dynamic]InventoryItem,
|
||||
current_slot: int,
|
||||
}
|
||||
hotbar := Hotbar {
|
||||
tool_slots = {.hoe, .scythe, .watering_can},
|
||||
seed_slots = {.tomato_seed},
|
||||
}
|
||||
|
||||
TOOL_SLOTS := len(hotbar.tool_slots)
|
||||
|
||||
update_hotbar :: proc() {
|
||||
if rl.IsKeyPressed(.E) {
|
||||
|
|
@ -95,9 +81,10 @@ update_hotbar :: proc() {
|
|||
draw_hotbar :: proc() {
|
||||
rl.DrawRectangleRec({TOOL_POS.x, TOOL_POS.y, 32, 32}, rl.WHITE)
|
||||
slots := hotbar.kind == .tools ? hotbar.tool_slots : hotbar.seed_slots
|
||||
hotbar_item_texture := ITEM_TEXTURES[slots[hotbar.current_slot]]^
|
||||
if len(slots) == 0 {return}
|
||||
hotbar_item_texture := ITEM_TEXTURES[slots[hotbar.current_slot]]
|
||||
rl.DrawTexturePro(
|
||||
hotbar_item_texture,
|
||||
hotbar_item_texture^,
|
||||
{0, 0, 16, 16},
|
||||
{TOOL_POS.x, TOOL_POS.y, 32, 32},
|
||||
{},
|
||||
|
|
@ -107,8 +94,50 @@ draw_hotbar :: proc() {
|
|||
|
||||
}
|
||||
|
||||
get_current_hand_item :: proc() -> InventoryItem {
|
||||
return(
|
||||
hotbar.kind == .tools ? hotbar.tool_slots[hotbar.current_slot] : hotbar.seed_slots[hotbar.current_slot] \
|
||||
)
|
||||
get_current_hand_item :: proc() -> (InventoryItem, bool) {
|
||||
slots := hotbar.kind == .tools ? hotbar.tool_slots : hotbar.seed_slots
|
||||
if len(slots) == 0 {
|
||||
return nil, false
|
||||
} else {
|
||||
return slots[hotbar.current_slot], true
|
||||
}
|
||||
}
|
||||
|
||||
init_hotbar_from_inventory :: proc() {
|
||||
clear(&hotbar.tool_slots)
|
||||
clear(&hotbar.seed_slots)
|
||||
for amount, item in player_inventory {
|
||||
switch item {
|
||||
case .hoe:
|
||||
fallthrough
|
||||
case .scythe:
|
||||
fallthrough
|
||||
case .watering_can:
|
||||
fallthrough
|
||||
case .pickaxe:
|
||||
fallthrough
|
||||
case .axe:
|
||||
if amount > 0 {
|
||||
append(&hotbar.tool_slots, item)
|
||||
}
|
||||
case .tomato_seed:
|
||||
if amount > 0 {
|
||||
append(&hotbar.seed_slots, item)
|
||||
}
|
||||
case .tomato:
|
||||
case .tomato_seedling:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_seed_hotbar :: proc() {
|
||||
clear(&hotbar.seed_slots)
|
||||
for amount, item in player_inventory {
|
||||
#partial switch item {
|
||||
case .tomato_seed:
|
||||
if amount > 0 {
|
||||
append(&hotbar.seed_slots, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ tile_dirt_dry_sprite: []u8 : #load("../assets/tile_dirt_dry.png")
|
|||
tile_dirt_wet_sprite: []u8 : #load("../assets/tile_dirt_wet.png")
|
||||
hoe_sprite: []u8 : #load("../assets/hoe.png")
|
||||
scythe_sprite: []u8 : #load("../assets/scythe.png")
|
||||
watering_can_sprite: []u8 : #load("../assets/watering_can.png")
|
||||
axe_sprite: []u8 : #load("../assets/axe.png")
|
||||
|
||||
pickup_sound: rl.Sound
|
||||
|
||||
|
|
@ -24,6 +26,8 @@ tile_dirt_wet_texture: rl.Texture2D
|
|||
tomato_texture: rl.Texture2D
|
||||
hoe_texture: rl.Texture2D
|
||||
scythe_texture: rl.Texture2D
|
||||
watering_can_texture: rl.Texture2D
|
||||
axe_texture: rl.Texture2D
|
||||
|
||||
player_animation: Animation
|
||||
tomato_animation: Animation
|
||||
|
|
@ -72,13 +76,18 @@ load_resources :: proc() {
|
|||
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)
|
||||
|
||||
sell_button_texture = load_texture_from_memory(sell_button_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)
|
||||
tomato_texture = load_texture_from_memory(tomato_item_sprite)
|
||||
|
||||
hoe_texture = load_texture_from_memory(hoe_sprite)
|
||||
scythe_texture = load_texture_from_memory(scythe_sprite)
|
||||
watering_can_texture = load_texture_from_memory(watering_can_sprite)
|
||||
axe_texture = load_texture_from_memory(axe_sprite)
|
||||
|
||||
pickup_sound = load_sound_from_memory(pickup_sound_data)
|
||||
rl.SetSoundVolume(pickup_sound, 0.1)
|
||||
|
|
@ -91,6 +100,29 @@ load_resources :: proc() {
|
|||
},
|
||||
)
|
||||
player_handle = entity_to_handle(e^)
|
||||
|
||||
// Starting inventory
|
||||
player_inventory[.tomato_seed] = 5
|
||||
player_inventory[.hoe] = 1
|
||||
player_inventory[.watering_can] = 1
|
||||
player_inventory[.scythe] = 1
|
||||
player_inventory[.axe] = 1
|
||||
|
||||
hotbar.tool_slots = make([dynamic]InventoryItem)
|
||||
hotbar.seed_slots = make([dynamic]InventoryItem)
|
||||
init_hotbar_from_inventory()
|
||||
|
||||
ITEM_TEXTURES = [InventoryItem]^rl.Texture2D {
|
||||
.hoe = &hoe_texture,
|
||||
.scythe = &scythe_texture,
|
||||
.watering_can = &watering_can_texture,
|
||||
.pickaxe = &tomato_texture,
|
||||
.axe = &axe_texture,
|
||||
.tomato = &tomato_texture,
|
||||
.tomato_seed = &tomato_texture,
|
||||
.tomato_seedling = &tomato_texture,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free_resources :: proc() {
|
||||
|
|
@ -99,11 +131,21 @@ free_resources :: proc() {
|
|||
|
||||
rl.UnloadSound(pickup_sound)
|
||||
|
||||
rl.UnloadTexture(tomato_texture)
|
||||
rl.UnloadTexture(sell_button_texture)
|
||||
rl.UnloadTexture(background_texture)
|
||||
|
||||
rl.UnloadTexture(tomato_texture)
|
||||
rl.UnloadTexture(tile_dirt_dry_texture)
|
||||
rl.UnloadTexture(tile_dirt_wet_texture)
|
||||
|
||||
rl.UnloadRenderTexture(game_render_buffer) // Unload render texture
|
||||
rl.UnloadTexture(hoe_texture)
|
||||
rl.UnloadTexture(scythe_texture)
|
||||
rl.UnloadTexture(watering_can_texture)
|
||||
rl.UnloadTexture(axe_texture)
|
||||
|
||||
rl.UnloadRenderTexture(game_render_buffer)
|
||||
|
||||
delete(hotbar.tool_slots)
|
||||
delete(hotbar.seed_slots)
|
||||
delete(entities)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ Tile :: struct {
|
|||
|
||||
interact_with_tile_under_mouse :: proc(mouse_button: rl.MouseButton) {
|
||||
tile_position := get_tile_position(world_mouse)
|
||||
current_hand_item := get_current_hand_item()
|
||||
current_hand_item, hok := get_current_hand_item();if !hok {
|
||||
return
|
||||
}
|
||||
|
||||
tile_entity: ^Entity
|
||||
for &e in entities {
|
||||
|
|
@ -51,8 +53,19 @@ interact_with_tile_under_mouse :: proc(mouse_button: rl.MouseButton) {
|
|||
pos = tile_entity.pos,
|
||||
kind = .Item,
|
||||
data = ItemData {
|
||||
id = get_seed_to_plant_id(tile_data.plant_id),
|
||||
id = get_plant_to_seed_id(tile_data.plant_id),
|
||||
count = 3,
|
||||
texture = get_seed_texture(tile_data.plant_id)^,
|
||||
},
|
||||
},
|
||||
)
|
||||
create_entity(
|
||||
Entity {
|
||||
pos = tile_entity.pos,
|
||||
kind = .Item,
|
||||
data = ItemData {
|
||||
id = get_seed_to_plant_id(tile_data.plant_id),
|
||||
count = 1,
|
||||
texture = get_plant_texture(tile_data.plant_id)^,
|
||||
},
|
||||
},
|
||||
|
|
@ -64,6 +77,8 @@ interact_with_tile_under_mouse :: proc(mouse_button: rl.MouseButton) {
|
|||
tile_data.has_plant = true
|
||||
tile_data.plant_id = current_hand_item
|
||||
tile_data.animation = get_plant_animation(current_hand_item)
|
||||
player_inventory[current_hand_item] -= 1
|
||||
update_seed_hotbar()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -73,6 +88,10 @@ 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}
|
||||
}
|
||||
|
||||
get_plant_to_seed_id :: proc(plant: InventoryItem) -> InventoryItem {
|
||||
return .tomato_seed
|
||||
}
|
||||
|
||||
get_seed_to_plant_id :: proc(seed: InventoryItem) -> InventoryItem {
|
||||
return .tomato
|
||||
}
|
||||
|
|
@ -82,7 +101,20 @@ get_plant_animation :: proc(plant: InventoryItem) -> Animation {
|
|||
}
|
||||
|
||||
get_plant_texture :: proc(plant: InventoryItem) -> ^rl.Texture2D {
|
||||
return ITEM_TEXTURES[plant]
|
||||
//#partial switch plant {
|
||||
//case .tomato_seed:
|
||||
// fallthrough
|
||||
//case .tomato:
|
||||
// fallthrough
|
||||
//case .tomato_seedling:
|
||||
// return ITEM_TEXTURES[.tomato]
|
||||
//}
|
||||
//return ITEM_TEXTURES[plant]
|
||||
return ITEM_TEXTURES[.tomato]
|
||||
}
|
||||
|
||||
get_seed_texture :: proc(plant: InventoryItem) -> ^rl.Texture2D {
|
||||
return ITEM_TEXTURES[.tomato_seed]
|
||||
}
|
||||
|
||||
update_tile :: proc(e: Entity, data: ^TileData) {
|
||||
|
|
@ -94,14 +126,19 @@ update_tile :: proc(e: Entity, data: ^TileData) {
|
|||
}
|
||||
}
|
||||
|
||||
draw_tile_plant :: proc(e: Entity) {
|
||||
data, ok := e.data.(TileData);if ok {
|
||||
if !data.is_tiled {return}
|
||||
if data.has_plant {
|
||||
draw_animation(data.animation, e.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
draw_tile :: proc(e: Entity) {
|
||||
data, ok := e.data.(TileData);if ok {
|
||||
if !data.is_tiled {return}
|
||||
|
||||
tile_tint := data.is_watered ? rl.SKYBLUE : rl.WHITE
|
||||
rl.DrawTextureV(tile_dirt_dry_texture, e.pos, tile_tint)
|
||||
if data.has_plant {
|
||||
draw_animation(data.animation, e.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue