575 lines
20 KiB
C
575 lines
20 KiB
C
#include "core.h"
|
|
#include "handmade.h"
|
|
#include "handmade_math.h"
|
|
#include "sdl_handmade.h"
|
|
|
|
#include "handmade_intrinsics.h"
|
|
#include "handmade_random.h"
|
|
#include "handmade_tile.h"
|
|
#include "handmade_tile.c"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h> /* memset */
|
|
|
|
static void GameOutputSound(game_state *GameState, game_sound_output_buffer *SoundBuffer, S32 ToneHz)
|
|
{
|
|
/*
|
|
S16 ToneVolume, *SampleOut;
|
|
S32 WavePeriod, SampleIndex;
|
|
|
|
ToneVolume = 0;
|
|
WavePeriod = SoundBuffer->SamplesPerSecond / ToneHz;
|
|
|
|
SampleOut = SoundBuffer->Samples;
|
|
|
|
for(SampleIndex = 0;
|
|
SampleIndex < SoundBuffer->SampleCount;
|
|
SampleIndex++)
|
|
{
|
|
F32 SineValue;
|
|
S16 SampleValue;
|
|
|
|
SineValue = sinf(GameState->tSine);
|
|
SampleValue = (S16)(SineValue * ToneVolume);
|
|
*SampleOut++ = SampleValue;
|
|
*SampleOut++ = SampleValue;
|
|
|
|
GameState->tSine += 2.0f * (F32)PI * 1.0f / (F32)WavePeriod;
|
|
if(GameState->tSine > 2.0f*(F32)PI) {
|
|
GameState->tSine -= 2.0f*(F32)PI;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
static void ClearBackground(game_offscreen_buffer *Buffer)
|
|
{
|
|
S32 Width = Buffer->Width;
|
|
S32 Height = Buffer->Height;
|
|
|
|
for(S32 X = 0; X < Width * Height; X++) {
|
|
U32 *Pixel = &((U32 *)Buffer->Memory)[X];
|
|
*Pixel = 0xFFFFFF;
|
|
}
|
|
}
|
|
|
|
static void DrawRectangle(game_offscreen_buffer *Buffer, v2 vMin, v2 vMax, F32 R, F32 G, F32 B)
|
|
{
|
|
S32 MinX = RoundF32toS32(vMin.X);
|
|
S32 MinY = RoundF32toS32(vMin.Y);
|
|
S32 MaxX = RoundF32toS32(vMax.X);
|
|
S32 MaxY = RoundF32toS32(vMax.Y);
|
|
|
|
S32 Width = Buffer->Width;
|
|
S32 Height = Buffer->Height;
|
|
|
|
if(MinX < 0)
|
|
MinX = 0;
|
|
if(MinY < 0)
|
|
MinY = 0;
|
|
|
|
if(MaxX > Width)
|
|
MaxX = Width;
|
|
if(MaxY > Height)
|
|
MaxY = Height;
|
|
|
|
U32 Color = (U32)((RoundF32toS32(R * 255.0f) << 16) | (RoundF32toS32(G * 255.0f) << 8) | (RoundF32toS32(B * 255.0f) << 0));
|
|
|
|
U8 *Row = ((U8 *)Buffer->Memory + MinX*Buffer->BytesPerPixel + MinY*Buffer->Pitch);
|
|
for(S32 Y = MinY; Y < MaxY; Y++) {
|
|
U32 *Pixel = (U32 *)Row;
|
|
for(S32 X = MinX; X < MaxX; X++) {
|
|
*(U32 *)Pixel = Color;
|
|
Pixel++;
|
|
}
|
|
Row += Buffer->Pitch;
|
|
}
|
|
}
|
|
|
|
static void DrawBitmap(game_offscreen_buffer *Buffer, loaded_bitmap *Bitmap, F32 RelX, F32 RelY, S32 AlignX, S32 AlignY)
|
|
{
|
|
RelX -= (F32)AlignX;
|
|
RelY -= (F32)AlignY;
|
|
|
|
S32 MinX = RoundF32toS32(RelX);
|
|
S32 MinY = RoundF32toS32(RelY);
|
|
S32 MaxX = RoundF32toS32(RelX + (F32)Bitmap->Width);
|
|
S32 MaxY = RoundF32toS32(RelY + (F32)Bitmap->Height);
|
|
|
|
S32 Width = Buffer->Width;
|
|
S32 Height = Buffer->Height;
|
|
|
|
S32 SourceOffsetX = 0;
|
|
if(MinX < 0) {
|
|
SourceOffsetX = -MinX;
|
|
MinX = 0;
|
|
}
|
|
|
|
S32 SourceOffsetY = 0;
|
|
if(MinY < 0) {
|
|
SourceOffsetY = -MinY;
|
|
MinY = 0;
|
|
}
|
|
|
|
if(MaxX > Width)
|
|
MaxX = Width;
|
|
if(MaxY > Height)
|
|
MaxY = Height;
|
|
|
|
U32 *SourceRow = Bitmap->Pixels + Bitmap->Width*(Bitmap->Height - 1);
|
|
SourceRow += -Bitmap->Width*SourceOffsetY + SourceOffsetX;
|
|
U8 *DestRow = ((U8 *)Buffer->Memory + MinX*Buffer->BytesPerPixel + MinY*Buffer->Pitch);
|
|
for(S32 Y = MinY; Y < MaxY; Y++) {
|
|
U32 *Dest = (U32 *)DestRow;
|
|
U32 *Source = SourceRow;
|
|
for(S32 X = MinX; X < MaxX; X++) {
|
|
F32 A = (F32)((*Source >> 24) & 0xFF) / 255.0f;
|
|
F32 SR = (F32)((*Source >> 16) & 0xFF);
|
|
F32 SG = (F32)((*Source >> 8) & 0xFF);
|
|
F32 SB = (F32)((*Source >> 0) & 0xFF);
|
|
|
|
F32 DR = (F32)((*Dest >> 16) & 0xFF);
|
|
F32 DG = (F32)((*Dest >> 8) & 0xFF);
|
|
F32 DB = (F32)((*Dest >> 0) & 0xFF);
|
|
|
|
// TODO: This should be replaced by premultiplied alpha.
|
|
F32 R = (1.0f-A)*DR + A*SR;
|
|
F32 G = (1.0f-A)*DG + A*SG;
|
|
F32 B = (1.0f-A)*DB + A*SB;
|
|
|
|
*Dest = (((U32)RoundF32toS32(R) << 16) | ((U32)RoundF32toS32(G) << 8) | ((U32)RoundF32toS32(B) << 0));
|
|
|
|
Dest++;
|
|
Source++;
|
|
}
|
|
DestRow += Buffer->Pitch;
|
|
SourceRow -= Bitmap->Width;
|
|
}
|
|
}
|
|
|
|
#pragma pack(push, 1)
|
|
typedef struct bitmap_header {
|
|
U16 FileType;
|
|
U32 FileSize;
|
|
U16 Reserved1;
|
|
U16 Reserved2;
|
|
U32 BitmapOffset;
|
|
U32 Size;
|
|
S32 Width;
|
|
S32 Height;
|
|
U16 Planes;
|
|
U16 BitsPerPixel;
|
|
U32 Compression;
|
|
U32 SizeOfBitmap;
|
|
S32 HorzResolution;
|
|
S32 VertResolution;
|
|
U32 ColorsUsed;
|
|
U32 ColorsImportant;
|
|
|
|
U32 RedMask;
|
|
U32 GreenMask;
|
|
U32 BlueMask;
|
|
} bitmap_header;
|
|
#pragma pack(pop)
|
|
|
|
static loaded_bitmap DEBUGLoadBMP(thread_context *Thread, debug_read_file_result (*DEBUGPlatformReadEntireFile)(thread_context *Thread, const char *), char *FileName)
|
|
{
|
|
loaded_bitmap Result;
|
|
memset(&Result, 0, sizeof(Result));
|
|
|
|
debug_read_file_result ReadResult = DEBUGPlatformReadEntireFile(Thread, FileName);
|
|
if(ReadResult.ContentsSize > 0) {
|
|
bitmap_header *Header = (bitmap_header *)ReadResult.Contents;
|
|
|
|
U32 *Pixels = (U32 *)((U8 *)ReadResult.Contents + Header->BitmapOffset);
|
|
Result.Pixels = Pixels;
|
|
Result.Width = Header->Width;
|
|
Result.Height = Header->Height;
|
|
|
|
ASSERT(Header->Compression == 3);
|
|
|
|
// NOTE: The byte order in memory is determined by the Header.
|
|
|
|
U32 RedMask = Header->RedMask;
|
|
U32 GreenMask = Header->GreenMask;
|
|
U32 BlueMask = Header->BlueMask;
|
|
U32 AlphaMask = ~(RedMask | GreenMask | BlueMask);
|
|
|
|
bit_scan_result RedShift = FindLeastSignificantSetBit(RedMask);
|
|
bit_scan_result GreenShift = FindLeastSignificantSetBit(GreenMask);
|
|
bit_scan_result BlueShift = FindLeastSignificantSetBit(BlueMask);
|
|
bit_scan_result AlphaShift = FindLeastSignificantSetBit(AlphaMask);
|
|
|
|
ASSERT(RedShift.Found);
|
|
ASSERT(GreenShift.Found);
|
|
ASSERT(BlueShift.Found);
|
|
ASSERT(AlphaShift.Found);
|
|
|
|
U32 *SourceDest = Pixels;
|
|
for(S32 Y = 0; Y < Header->Height; Y++) {
|
|
for(S32 X = 0; X < Header->Width; X++) {
|
|
U32 C = *SourceDest;
|
|
|
|
*SourceDest = ((((C >> AlphaShift.Index) & 0xFF) << 24) |
|
|
(((C >> RedShift.Index ) & 0xFF) << 16) |
|
|
(((C >> GreenShift.Index) & 0xFF) << 8) |
|
|
(((C >> BlueShift.Index ) & 0xFF) << 0));
|
|
SourceDest++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
void UpdateAndRender(thread_context *Thread, game_memory *Memory, game_input *Input, game_offscreen_buffer *Buffer, game_sound_output_buffer *SoundBuffer)
|
|
{
|
|
ASSERT((&Input->Controllers[0].Terminator - &Input->Controllers[0].Buttons[0]) == ARRAY_SIZE(Input->Controllers[0].Buttons));
|
|
ASSERT(sizeof(game_state) <= Memory->PermanentStorageSize);
|
|
|
|
game_state *GameState;
|
|
|
|
F32 PlayerHeight = 1.4f;
|
|
F32 PlayerWidth = 0.75f * PlayerHeight;
|
|
|
|
GameState = (game_state *)Memory->PermanentStorage;
|
|
if(!Memory->IsInitialized) {
|
|
GameState->Backdrop = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_background.bmp");
|
|
|
|
hero_bitmaps *Bitmap;
|
|
|
|
Bitmap = &GameState->HeroBitmaps[0];
|
|
Bitmap->AlignX = 72;
|
|
Bitmap->AlignY = 182;
|
|
Bitmap->Head = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_right_head.bmp");
|
|
Bitmap->Cape = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_right_cape.bmp");
|
|
Bitmap->Torso = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_right_torso.bmp");
|
|
Bitmap++;
|
|
|
|
Bitmap->AlignX = 72;
|
|
Bitmap->AlignY = 182;
|
|
Bitmap->Head = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_back_head.bmp");
|
|
Bitmap->Cape = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_back_cape.bmp");
|
|
Bitmap->Torso = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_back_torso.bmp");
|
|
Bitmap++;
|
|
|
|
Bitmap->AlignX = 72;
|
|
Bitmap->AlignY = 182;
|
|
Bitmap->Head = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_left_head.bmp");
|
|
Bitmap->Cape = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_left_cape.bmp");
|
|
Bitmap->Torso = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_left_torso.bmp");
|
|
Bitmap++;
|
|
|
|
Bitmap->AlignX = 72;
|
|
Bitmap->AlignY = 182;
|
|
Bitmap->Head = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_front_head.bmp");
|
|
Bitmap->Cape = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_front_cape.bmp");
|
|
Bitmap->Torso = DEBUGLoadBMP(Thread, Memory->DEBUGPlatformReadEntireFile, "data/test_hero_front_torso.bmp");
|
|
|
|
GameState->CameraP.AbsTileX = 17 / 2;
|
|
GameState->CameraP.AbsTileY = 9 / 2;
|
|
|
|
GameState->PlayerP.AbsTileX = 2;
|
|
GameState->PlayerP.AbsTileY = 3;
|
|
GameState->PlayerP.Offset.X = 5.0f;
|
|
GameState->PlayerP.Offset.Y = 5.0f;
|
|
|
|
InitializeArena(&GameState->WorldArena, Memory->PermanentStorageSize - sizeof(game_state), (U8 *)Memory->PermanentStorage + sizeof(game_state));
|
|
|
|
GameState->World = PUSH_STRUCT(&GameState->WorldArena, world);
|
|
world *World = GameState->World;
|
|
World->TileMap = PUSH_STRUCT(&GameState->WorldArena, tile_map);
|
|
|
|
tile_map *TileMap = World->TileMap;
|
|
|
|
TileMap->ChunkShift = 4;
|
|
TileMap->ChunkMask = (1 << TileMap->ChunkShift) - 1;
|
|
TileMap->ChunkDim = (1 << TileMap->ChunkShift);
|
|
|
|
TileMap->TileChunkCountX = 128;
|
|
TileMap->TileChunkCountY = 128;
|
|
TileMap->TileChunkCountZ = 2;
|
|
|
|
TileMap->TileChunks = PUSH_ARRAY(&GameState->WorldArena, TileMap->TileChunkCountX * TileMap->TileChunkCountY * TileMap->TileChunkCountZ, tile_chunk);
|
|
|
|
TileMap->TileSideInMeters = 1.4f;
|
|
|
|
U32 RandomNumberIndex = 0;
|
|
|
|
U32 TilesPerWidth = 17;
|
|
U32 TilesPerHeight = 9;
|
|
U32 ScreenX = 0;
|
|
U32 ScreenY = 0;
|
|
|
|
U32 AbsTileZ = 0;
|
|
|
|
B32 DoorTop = FALSE;
|
|
B32 DoorBottom = FALSE;
|
|
B32 DoorLeft = FALSE;
|
|
B32 DoorRight = FALSE;
|
|
B32 DoorUp = FALSE;
|
|
B32 DoorDown = FALSE;
|
|
for(U32 ScreenIndex = 0; ScreenIndex < 100; ScreenIndex++) {
|
|
ASSERT(RandomNumberIndex < ARRAY_SIZE(RandomNumberTable));
|
|
|
|
/* TODO: Random number generator. */
|
|
U32 RandomChoice;
|
|
if(DoorUp || DoorDown) {
|
|
RandomChoice = RandomNumberTable[RandomNumberIndex++] % 2;
|
|
} else {
|
|
RandomChoice = RandomNumberTable[RandomNumberIndex++] % 3;
|
|
}
|
|
|
|
B32 CreatedZDoor = FALSE;
|
|
|
|
if(RandomChoice == 2) {
|
|
CreatedZDoor = TRUE;
|
|
|
|
if(AbsTileZ == 0) {
|
|
DoorUp = TRUE;
|
|
} else {
|
|
DoorDown = TRUE;
|
|
}
|
|
} else if(RandomChoice == 1) {
|
|
DoorRight = TRUE;
|
|
} else {
|
|
DoorTop = TRUE;
|
|
}
|
|
|
|
for(U32 TileY = 0; TileY < TilesPerHeight; TileY++) {
|
|
for(U32 TileX = 0; TileX < TilesPerWidth; TileX++) {
|
|
U32 AbsTileX = ScreenX * TilesPerWidth + TileX;
|
|
U32 AbsTileY = ScreenY * TilesPerHeight + TileY;
|
|
|
|
U32 TileValue = 1;
|
|
if((TileX == 0) && (!DoorLeft || (TileY != (TilesPerHeight/2)))) {
|
|
TileValue = 2;
|
|
}
|
|
|
|
if(((TileX == (TilesPerWidth - 1)) && (!DoorRight || (TileY != (TilesPerHeight/2))))) {
|
|
TileValue = 2;
|
|
}
|
|
|
|
if((TileY == 0) && (!DoorBottom || (TileX != (TilesPerWidth/2)))) {
|
|
TileValue = 2;
|
|
}
|
|
|
|
if((TileY == (TilesPerHeight - 1)) && (!DoorTop || (TileX != (TilesPerWidth/2)))) {
|
|
TileValue = 2;
|
|
}
|
|
|
|
if((TileX == 10) && (TileY == 6)) {
|
|
if(DoorUp) {
|
|
TileValue = 3;
|
|
}
|
|
if(DoorDown) {
|
|
TileValue = 4;
|
|
}
|
|
}
|
|
|
|
SetTileValue(&GameState->WorldArena, World->TileMap, AbsTileX, AbsTileY, AbsTileZ, TileValue);
|
|
}
|
|
}
|
|
|
|
DoorLeft = DoorRight;
|
|
DoorBottom = DoorTop;
|
|
|
|
if(CreatedZDoor) {
|
|
DoorDown = !DoorDown;
|
|
DoorUp = !DoorUp;
|
|
} else {
|
|
DoorUp = FALSE;
|
|
DoorDown = FALSE;
|
|
}
|
|
|
|
DoorTop = FALSE;
|
|
DoorRight = FALSE;
|
|
|
|
if(RandomChoice == 2) {
|
|
if(AbsTileZ == 0) {
|
|
AbsTileZ = 1;
|
|
} else {
|
|
AbsTileZ = 0;
|
|
}
|
|
} else if(RandomChoice == 1) {
|
|
ScreenX++;
|
|
} else {
|
|
ScreenY++;
|
|
}
|
|
}
|
|
|
|
Memory->IsInitialized = TRUE;
|
|
}
|
|
|
|
world *World = GameState->World;
|
|
tile_map *TileMap = World->TileMap;
|
|
|
|
S32 TileSideInPixels = 60;
|
|
F32 MetersToPixels = (F32)TileSideInPixels / TileMap->TileSideInMeters;
|
|
|
|
for(U32 ControllerIndex = 0; ControllerIndex < ARRAY_SIZE(Input->Controllers); ControllerIndex++) {
|
|
game_controller_input *Controller = GetController(Input, ControllerIndex);
|
|
if(Controller->IsAnalog) {
|
|
} else {
|
|
v2 dPlayer;
|
|
memset(&dPlayer, 0, sizeof(dPlayer));
|
|
|
|
if(Controller->MoveUp.EndedDown) {
|
|
dPlayer.Y = 1.0f;
|
|
GameState->FacingDirection = 1;
|
|
}
|
|
if(Controller->MoveDown.EndedDown) {
|
|
dPlayer.Y = -1.0f;
|
|
GameState->FacingDirection = 3;
|
|
}
|
|
if(Controller->MoveLeft.EndedDown) {
|
|
dPlayer.X = -1.0f;
|
|
GameState->FacingDirection = 2;
|
|
}
|
|
if(Controller->MoveRight.EndedDown) {
|
|
dPlayer.X = 1.0f;
|
|
GameState->FacingDirection = 0;
|
|
}
|
|
|
|
F32 PlayerSpeed = 2.0f;
|
|
if(Controller->ActionUp.EndedDown)
|
|
PlayerSpeed = 10.0f;
|
|
dPlayer = vector_multiply(PlayerSpeed, dPlayer);
|
|
|
|
if((dPlayer.X != 0.0f) && (dPlayer.Y != 0.0f))
|
|
dPlayer = vector_multiply(0.7071067811865475244f, dPlayer);
|
|
|
|
tile_map_position NewPlayerP;
|
|
NewPlayerP = GameState->PlayerP;
|
|
NewPlayerP.Offset = vector_add(NewPlayerP.Offset, vector_multiply(Input->dtForFrame, dPlayer));
|
|
NewPlayerP = RecannonicalizePosition(TileMap, NewPlayerP);
|
|
|
|
tile_map_position PlayerLeft;
|
|
PlayerLeft = NewPlayerP;
|
|
PlayerLeft.Offset.X -= 0.5f*PlayerWidth;
|
|
PlayerLeft = RecannonicalizePosition(TileMap, PlayerLeft);
|
|
|
|
tile_map_position PlayerRight;
|
|
PlayerRight = NewPlayerP;
|
|
PlayerRight.Offset.X += 0.5f*PlayerWidth;
|
|
PlayerRight = RecannonicalizePosition(TileMap, PlayerRight);
|
|
|
|
if(IsTileMapPointEmpty(TileMap, NewPlayerP) && IsTileMapPointEmpty(TileMap, PlayerLeft) && IsTileMapPointEmpty(TileMap, PlayerRight)) {
|
|
if(!AreOnSameTile(&GameState->PlayerP, &NewPlayerP)) {
|
|
U32 NewTileValue = GetTileValueByPos(TileMap, NewPlayerP);
|
|
|
|
if(NewTileValue == 3) {
|
|
NewPlayerP.AbsTileZ++;
|
|
} else if(NewTileValue == 4) {
|
|
NewPlayerP.AbsTileZ--;
|
|
}
|
|
}
|
|
GameState->PlayerP = NewPlayerP;
|
|
}
|
|
|
|
GameState->CameraP.AbsTileZ = GameState->PlayerP.AbsTileZ;
|
|
|
|
tile_map_difference Diff = SubtractInF32(TileMap, &GameState->PlayerP, &GameState->CameraP);
|
|
if(Diff.dXY.X > (9.0f*TileMap->TileSideInMeters)) {
|
|
GameState->CameraP.AbsTileX += 17;
|
|
}
|
|
if(Diff.dXY.X < -(9.0f*TileMap->TileSideInMeters)) {
|
|
GameState->CameraP.AbsTileX -= 17;
|
|
}
|
|
if(Diff.dXY.Y > (5.0f*TileMap->TileSideInMeters)) {
|
|
GameState->CameraP.AbsTileY += 9;
|
|
}
|
|
if(Diff.dXY.Y < -(5.0f*TileMap->TileSideInMeters)) {
|
|
GameState->CameraP.AbsTileY -= 9;
|
|
}
|
|
}
|
|
}
|
|
|
|
//DrawRectangle(Buffer, 0.0f, 0.0f, (F32)Buffer->Width, (F32)Buffer->Height, 0.0f, 1.0f, 0.0f);
|
|
|
|
DrawBitmap(Buffer, &GameState->Backdrop, 0.0f, 0.0f, 0, 0);
|
|
|
|
F32 ScreenCenterX = 0.5f * (F32)Buffer->Width;
|
|
F32 ScreenCenterY = 0.5f * (F32)Buffer->Height;
|
|
|
|
for(S32 RelRow = -10; RelRow < 10; RelRow++) {
|
|
for(S32 RelColumn = -20; RelColumn < 20; RelColumn++) {
|
|
U32 Column = GameState->CameraP.AbsTileX + RelColumn;
|
|
U32 Row = GameState->CameraP.AbsTileY + RelRow;
|
|
|
|
U32 TileID = GetTileValue(TileMap, Column, Row, GameState->CameraP.AbsTileZ);
|
|
|
|
if(TileID > 1) {
|
|
F32 Gray = 0.5f;
|
|
if(TileID == 2) {
|
|
Gray = 1.0f;
|
|
}
|
|
|
|
if(TileID > 2) {
|
|
Gray = 0.25f;
|
|
}
|
|
|
|
if((Column == GameState->CameraP.AbsTileX) && (Row == GameState->CameraP.AbsTileY)) {
|
|
Gray = 0.0f;
|
|
}
|
|
|
|
v2 TileSide = { 0.5f*(F32)TileSideInPixels, 0.5f*(F32)TileSideInPixels };
|
|
v2 Center = { ScreenCenterX - MetersToPixels*GameState->CameraP.Offset.X + (F32)RelColumn*(F32)TileSideInPixels,
|
|
ScreenCenterY + MetersToPixels*GameState->CameraP.Offset.Y - (F32)RelRow*(F32)TileSideInPixels };
|
|
v2 Min = vector_subtract(Center, TileSide);
|
|
v2 Max = vector_add(Center, TileSide);
|
|
DrawRectangle(Buffer, Min, Max, Gray, Gray, Gray);
|
|
}
|
|
}
|
|
}
|
|
|
|
tile_map_difference Diff = SubtractInF32(TileMap, &GameState->PlayerP, &GameState->CameraP);
|
|
|
|
F32 PlayerR = 1.0f;
|
|
F32 PlayerG = 0.0f;
|
|
F32 PlayerB = 0.0f;
|
|
F32 PlayerGroundPointX = ScreenCenterX + MetersToPixels*Diff.dXY.X;
|
|
F32 PlayerGroundPointY = ScreenCenterY - MetersToPixels*Diff.dXY.Y;
|
|
v2 PlayerLeftTop = { PlayerGroundPointX - 0.5f * MetersToPixels*PlayerWidth,
|
|
PlayerGroundPointY - MetersToPixels*PlayerHeight };
|
|
v2 PlayerWidthHeight = { PlayerWidth, PlayerHeight };
|
|
DrawRectangle(Buffer, PlayerLeftTop, vector_add(PlayerLeftTop, vector_multiply(MetersToPixels, PlayerWidthHeight)), PlayerR, PlayerG, PlayerB);
|
|
|
|
hero_bitmaps *Bitmap = &GameState->HeroBitmaps[GameState->FacingDirection];
|
|
DrawBitmap(Buffer, &Bitmap->Torso, PlayerGroundPointX, PlayerGroundPointY, Bitmap->AlignX, Bitmap->AlignY);
|
|
DrawBitmap(Buffer, &Bitmap->Cape, PlayerGroundPointX, PlayerGroundPointY, Bitmap->AlignX, Bitmap->AlignY);
|
|
DrawBitmap(Buffer, &Bitmap->Head, PlayerGroundPointX, PlayerGroundPointY, Bitmap->AlignX, Bitmap->AlignY);
|
|
|
|
GameOutputSound(GameState, SoundBuffer, 400);
|
|
}
|
|
|
|
/*
|
|
static void RenderWeirdGradient(game_offscreen_buffer *Buffer, S32 XOffset,
|
|
S32 YOffset)
|
|
{
|
|
S32 Width, Height, Y;
|
|
U8 *Row;
|
|
|
|
Width = Buffer->Width;
|
|
Height = Buffer->Height;
|
|
|
|
Row = (U8 *)Buffer->Memory;
|
|
for(Y = 0; Y < Height; Y++) {
|
|
U32 *Pixel = (U32 *)Row;
|
|
S32 X;
|
|
|
|
Pixel = (U32 *)Row;
|
|
for(X = 0; X < Width; X++) {
|
|
U8 Blue, Green;
|
|
|
|
Blue = (U8)(X + XOffset);
|
|
Green = (U8)(Y + YOffset);
|
|
|
|
*Pixel = (Green << 8) | Blue;
|
|
Pixel++;
|
|
}
|
|
Row += Buffer->Pitch;
|
|
}
|
|
}
|
|
*/
|