diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..91f29a1 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2019 iProgramInCpp + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..782e2db --- /dev/null +++ b/Makefile @@ -0,0 +1,194 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +.SECONDARY: + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro) +endif + +include $(DEVKITARM)/base_rules + +PORTLIBS := $(PORTLIBS_PATH)/nds $(PORTLIBS_PATH)/armv5te + +LIBNDS := $(DEVKITPRO)/libnds + +ifeq ($(strip $(GAME_TITLE)),) +GAME_TITLE := game +endif + +ifeq ($(strip $(GAME_SUBTITLE1)),) +GAME_SUBTITLE1 := test +endif + +ifeq ($(strip $(GAME_SUBTITLE2)),) +GAME_SUBTITLE2 := Made by iProgramInCpp +endif + +ifeq ($(strip $(GAME_ICON)),) +GAME_ICON := $(DEVKITPRO)/libnds/icon.bmp +endif + +ifneq ($(strip $(NITRO_FILES)),) +_ADDFILES := -d $(NITRO_FILES) +endif + +#--------------------------------------------------------------------------------- +%.nds: %.arm9 + $(SILENTCMD)ndstool -c $@ -9 $< -b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" $(_ADDFILES) + @echo built ... $(notdir $@) + +#--------------------------------------------------------------------------------- +%.nds: %.elf + ndstool -c $@ -9 $< -b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" $(_ADDFILES) -h 0x200 + $(SILENTMSG) built ... $(notdir $@) + +#--------------------------------------------------------------------------------- +%.arm9: %.elf + $(SILENTCMD)$(OBJCOPY) -O binary $< $@ + $(SILENTMSG) built ... $(notdir $@) + +#--------------------------------------------------------------------------------- +%.arm7: %.elf + $(SILENTCMD)$(OBJCOPY) -O binary $< $@ + $(SILENTMSG) built ... $(notdir $@) + +#--------------------------------------------------------------------------------- +%.elf: + $(SILENTMSG) linking $(notdir $@) + $(SILENTCMD)$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := $(shell basename $(CURDIR)) +BUILD := build +SOURCES := source +DATA := +INCLUDES := include +GRAPHICS := data + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb -mthumb-interwork + +CFLAGS := -g -Wall -O2\ + -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ + -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++14 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lfat -lnds9 + + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(PNGFILES:.png=.o) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).ds.gba + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).nds : $(OUTPUT).elf +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +#--------------------------------------------------------------------------------- +%.s %.h : %.png %.grit +#--------------------------------------------------------------------------------- + grit $< -fts -o$* + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/README.md b/README.md index cc1f568..9a1bc45 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,16 @@ -# DSPlatformMaker -Platformer game maker for the Nintendo DS. +# DSGameEngine +A DS game engine based off libnds with frame buffer capabilities for the top screen. + +It includes basic image drawing functions with transparency and flipping, and basic rectangle drawing. + +The graphics work is all done in software, only that the CPU will copy the framebuffer data to the GPU of the Nintendo DS. + +It's quite inefficient, but who needs backgrounds and sprites when you can have this? + + +This repo will also have examples of programs written based off it. + +The platform game contains sprites from New Super Mario Bros. for the Nintendo DS. I won't provide them here for legal reasons. +The 3D engine doesn't contain any other things. + +You need devkitPro (namely devkitARM) to build. diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..c0a4b19 --- /dev/null +++ b/build.bat @@ -0,0 +1,8 @@ +@echo off +cd C:\Users\iProgramInCpp\Desktop\game +rem set DEVKITARM=C:\devkitPro\devkitARM +rem set DEVKITPRO=C:\devkitPro +rem set PATH=C:\devkitPro\msys2 +rem msys2_shell.bat C:\Users\iProgramInCpp\Desktop\game\build.sh +make +pause \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..39ecd9b --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +cd /home/iProgramInCpp/Desktop/game +export DEVKITPRO=C:/Devkitpro/ +export DEVKITARM=C:/Devkitpro/Devkitarm +make +read -p "Press [Enter] key to start backup..." \ No newline at end of file diff --git a/clean.bat b/clean.bat new file mode 100644 index 0000000..2869d56 --- /dev/null +++ b/clean.bat @@ -0,0 +1,7 @@ +@echo off +rem cd C:\Users\Myria\Desktop\DSGAME +rem set DEVKITARM=C:\devkitPro\devkitARM +rem set DEVKITPRO=C:\devkitPro +rem set PATH=C:\devkitPro\msys2 +rem msys2_shell.bat C:\Users\Myria\Desktop\DSGAME\clean.sh +make clean \ No newline at end of file diff --git a/clean.sh b/clean.sh new file mode 100644 index 0000000..a2eb20e --- /dev/null +++ b/clean.sh @@ -0,0 +1,2 @@ +cd /home/Myria/Desktop/DSGAME +clean \ No newline at end of file diff --git a/data/bmpfont.png b/data/bmpfont.png new file mode 100644 index 0000000..edd1048 Binary files /dev/null and b/data/bmpfont.png differ diff --git a/data/character.png b/data/character.png new file mode 100644 index 0000000..2c517af Binary files /dev/null and b/data/character.png differ diff --git a/data/clapperboard.png b/data/clapperboard.png new file mode 100644 index 0000000..c1b974a Binary files /dev/null and b/data/clapperboard.png differ diff --git a/data/copy_mode.png b/data/copy_mode.png new file mode 100644 index 0000000..f8d7b49 Binary files /dev/null and b/data/copy_mode.png differ diff --git a/data/dialog_bg.png b/data/dialog_bg.png new file mode 100644 index 0000000..d293f34 Binary files /dev/null and b/data/dialog_bg.png differ diff --git a/data/dialogbtn.png b/data/dialogbtn.png new file mode 100644 index 0000000..b545131 Binary files /dev/null and b/data/dialogbtn.png differ diff --git a/data/erase.png b/data/erase.png new file mode 100644 index 0000000..c733c04 Binary files /dev/null and b/data/erase.png differ diff --git a/data/erase_mode.png b/data/erase_mode.png new file mode 100644 index 0000000..449e4a9 Binary files /dev/null and b/data/erase_mode.png differ diff --git a/data/item.png b/data/item.png new file mode 100644 index 0000000..ee11b3e Binary files /dev/null and b/data/item.png differ diff --git a/data/itemsel.png b/data/itemsel.png new file mode 100644 index 0000000..6b49714 Binary files /dev/null and b/data/itemsel.png differ diff --git a/data/logo.png b/data/logo.png new file mode 100644 index 0000000..8fa24b5 Binary files /dev/null and b/data/logo.png differ diff --git a/data/lr_arrows.png b/data/lr_arrows.png new file mode 100644 index 0000000..0e93dbd Binary files /dev/null and b/data/lr_arrows.png differ diff --git a/data/reset.png b/data/reset.png new file mode 100644 index 0000000..90e42a3 Binary files /dev/null and b/data/reset.png differ diff --git a/data/tiles.png b/data/tiles.png new file mode 100644 index 0000000..e5f6d05 Binary files /dev/null and b/data/tiles.png differ diff --git a/data/undo.png b/data/undo.png new file mode 100644 index 0000000..c771df8 Binary files /dev/null and b/data/undo.png differ diff --git a/data/zombie.png b/data/zombie.png new file mode 100644 index 0000000..01badcb Binary files /dev/null and b/data/zombie.png differ diff --git a/run.bat b/run.bat new file mode 100644 index 0000000..d3ffc89 --- /dev/null +++ b/run.bat @@ -0,0 +1,2 @@ +cd desmume +desmume.exe ..\DSGAME.nds \ No newline at end of file diff --git a/source/Enemy.cpp b/source/Enemy.cpp new file mode 100644 index 0000000..803d281 --- /dev/null +++ b/source/Enemy.cpp @@ -0,0 +1,232 @@ +#include "Enemy.hpp" + + +#include "zombie.h" + +glImage* mushroomImage; +glImage zombieImage[8]; +short zombieBmp[128*16]; +int zombSpriteID; + +Enemy::Enemy() { + +} +Enemy::~Enemy() { + +} + +void Enemy::Update (float fElapsedTime) { + if (this->posY > nLevelHeight) return; + if (this->posX > nLevelWidth) return; + if (this->posX < 0) return; + if (this->markForRemoval) return; + switch (type) { + case Enemy_Mushroom: + case Enemy_LifeUp: { + if (mushroom.risingTimer > 0.0f) { + if ((BlockBumpedX != (int)homeX || BlockBumpedY != (int)homeY)) { + mushroom.risingTimer -= fElapsedTime; + posY -= fElapsedTime; + if (mushroom.risingTimer <= 0.0f) { + mushroom.risingTimer = 0.0f; + } + } + velX = 5; + } else { + // gravity + velY += 20.0f * fElapsedTime; + isOnGround = false; + for (int i = 0; i < 5; i++) { + float newX = posX + fElapsedTime * velX * .2f; + float newY = posY + fElapsedTime * velY * .2f; + + if (velX < 0) { + if (IsSolid(GetTile(newX + 0.0f, posY + 0.0f), DIR_LEFT) || + IsSolid(GetTile(newX + 0.0f, posY + 0.9f), DIR_LEFT)) { + velX = -velX; + newX = (int)newX + 1; + } + } else if (velX > 0) { + if (IsSolid(GetTile(newX + 1.0f, posY + 0.0f), DIR_RIGHT) || + IsSolid(GetTile(newX + 1.0f, posY + 0.9f), DIR_RIGHT)) { + velX = -velX; + newX = (int)newX; + } + } + if (velY < 0) { + // no triggering blocks + if (IsSolid(GetTile(newX + 0.0f, newY), DIR_UP) || + IsSolid(GetTile(newX + 0.9f, newY), DIR_UP)) { + velY = 0; + newY = (int)newY + 1; + } + } + if (velY > 0) { + if (IsSolid(GetTile(newX + 0.0f, newY + 1.0f), DIR_DOWN) || + IsSolid(GetTile(newX + 0.9f, newY + 1.0f), DIR_DOWN)) { + velY = 0; + newY = (int)newY; + } + } + posX = newX; posY = newY; + } + if (isOnGround) { + if (velX == 0) velX = 5; + } + Rectangle ri = { (int)(posX * 100), (int)(posY * 100), 100, 100}; + Rectangle rp = { (int)(fPlayerPosX * 100 + 20), (int)(fPlayerPosY * 100), 100, 80 }; + if (RectangleIntersect(ri, rp)) { + if (type == Enemy_LifeUp) + IncreaseMaxHP(); + else + HealPlayer(); + // have to be overlapping with the mushroom quite a bit + this->markForRemoval = true; + score += 1000; // todo: increase lives + } + } + break; + } + case Enemy_Flower: + case Enemy_Time: { + if (mushroom.risingTimer > 0.0f) { + if ((BlockBumpedX != (int)homeX || BlockBumpedY != (int)homeY)) { + mushroom.risingTimer -= fElapsedTime; + posY -= fElapsedTime; + if (mushroom.risingTimer <= 0.0f) { + mushroom.risingTimer = 0.0f; + } + } + } else { + // gravity + velY += 20.0f * fElapsedTime; + isOnGround = false; + for (int i = 0; i < 5; i++) { + float newX = posX + fElapsedTime * velX * .2f; + float newY = posY + fElapsedTime * velY * .2f; + + if (velX < 0) { + if (IsSolid(GetTile(newX + 0.0f, posY + 0.0f), DIR_LEFT) || + IsSolid(GetTile(newX + 0.0f, posY + 0.9f), DIR_LEFT)) { + velX = -velX; + newX = (int)newX + 1; + } + } else if (velX > 0) { + if (IsSolid(GetTile(newX + 1.0f, posY + 0.0f), DIR_RIGHT) || + IsSolid(GetTile(newX + 1.0f, posY + 0.9f), DIR_RIGHT)) { + velX = -velX; + newX = (int)newX; + } + } + if (velY < 0) { + // no triggering blocks + if (IsSolid(GetTile(newX + 0.0f, newY), DIR_UP) || + IsSolid(GetTile(newX + 0.9f, newY), DIR_UP)) { + velY = 0; + newY = (int)newY + 1; + } + } + if (velY > 0) { + if (IsSolid(GetTile(newX + 0.0f, newY + 1.0f), DIR_DOWN) || + IsSolid(GetTile(newX + 0.9f, newY + 1.0f), DIR_DOWN)) { + velY = 0; + newY = (int)newY; + } + } + posX = newX; posY = newY; + } + Rectangle ri = { (int)(posX * 100), (int)(posY * 100), 100, 100}; + // offset the player rectangle a bit to avoid collecting while inside the box + Rectangle rp = { (int)(fPlayerPosX * 100 + 20), (int)(fPlayerPosY * 100), 100, 80 }; + if (RectangleIntersect(ri, rp)) { + // have to be overlapping with the mushroom quite a bit + this->markForRemoval = true; + score += 1000; + if (type == Enemy_Time) { + inGameTime += 10.f; + } else { + DamagePlayer(); + } + } + } + break; + } + } +} + +void Enemy::CommonDrawAtOffset(glImage* img, float pX, float pY, float oX, float oY, int flipMode) { + int sx = (posX - oX) * 16; + int sy = (posY - oY) * 16 + 1; + //glSprite(sx, sy, flipMode, img); + DrawImage(img, img->width, img->height, sx, sy); +} + +void Enemy::Draw (float fOffsetX, float fOffsetY) { + glImage* toDraw = nullptr; + int flipMode = 0; + switch (type) { + case Enemy_Mushroom: { + flipMode = this->mushroom.movingLeft ? GL_FLIP_H : 0; + // This should move the mushroom to behind the blocks during its rise anim + if ((BlockBumpedX != (int)homeX || BlockBumpedY != (int)homeY)) { + CommonDrawAtOffset(&tilesImage[33], posX, posY, fOffsetX, fOffsetY, flipMode); + if (homeX != 0 || homeY != 0) { + int mx = (homeX - fOffsetX) * 16; + int my = (homeY - fOffsetY) * 16; + DrawTile('U',mx,my,'.'); + } + } + break; + } + case Enemy_Flower: { + flipMode = this->mushroom.movingLeft ? GL_FLIP_H : 0; + // This should move the mushroom to behind the blocks during its rise anim + if ((BlockBumpedX != (int)homeX || BlockBumpedY != (int)homeY)) { + CommonDrawAtOffset(&tilesImage[36], posX, posY, fOffsetX, fOffsetY, flipMode); + if (homeX != 0 || homeY != 0) { + int mx = (homeX - fOffsetX) * 16; + int my = (homeY - fOffsetY) * 16; + DrawTile('U',mx,my,'.'); + } + } + break; + } + case Enemy_Time: { + flipMode = this->mushroom.movingLeft ? GL_FLIP_H : 0; + // This should move the mushroom to behind the blocks during its rise anim + if ((BlockBumpedX != (int)homeX || BlockBumpedY != (int)homeY)) { + CommonDrawAtOffset(&tilesImage[37], posX, posY, fOffsetX, fOffsetY, flipMode); + if (homeX != 0 || homeY != 0) { + int mx = (homeX - fOffsetX) * 16; + int my = (homeY - fOffsetY) * 16; + DrawTile('U',mx,my,'.'); + } + } + break; + } + case Enemy_LifeUp: { + flipMode = this->mushroom.movingLeft ? GL_FLIP_H : 0; + // This should move the mushroom to behind the blocks during its rise anim + if ((BlockBumpedX != (int)homeX || BlockBumpedY != (int)homeY)) { + CommonDrawAtOffset(&tilesImage[38], posX, posY, fOffsetX, fOffsetY, flipMode); + if (homeX != 0 || homeY != 0) { + int mx = (homeX - fOffsetX) * 16; + int my = (homeY - fOffsetY) * 16; + DrawTile('U',mx,my,'.'); + } + } + break; + } + case Enemy_Zombie: + flipMode = this->zombie.movingLeft ? GL_FLIP_H : 0; + toDraw = &zombieImage[1]; + CommonDrawAtOffset(toDraw, posX, posY, fOffsetX, fOffsetY, flipMode); + break; + } +} + +void Enemy::CommonLoad() { + mushroomImage = &tilesImage[33]; + decompress(zombieBitmap, zombieBmp, LZ77); + zombSpriteID = glLoadTileSet(zombieImage,16,16,128,16, GL_RGBA, TEXTURE_SIZE_128, TEXTURE_SIZE_16, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)zombieBmp); +} \ No newline at end of file diff --git a/source/Enemy.hpp b/source/Enemy.hpp new file mode 100644 index 0000000..29a84fa --- /dev/null +++ b/source/Enemy.hpp @@ -0,0 +1,31 @@ +#include "TestGame.hpp" + +#define Enemy_Mushroom 1 +#define Enemy_Zombie 2 +#define Enemy_Flower 3 +#define Enemy_Time 4 +#define Enemy_LifeUp 5 + +class Enemy { +public: + int type; + float posX = 0, posY = 0; + float homeX = 0, homeY = 0; + float velX = 0, velY = 0; + bool isOnGround = false; + bool markForRemoval = false; + union { + struct { + bool movingLeft = false; + float risingTimer = 0.0f; + } mushroom; + struct { + bool movingLeft = false; + } zombie; + }; + Enemy(); ~Enemy(); + void CommonDrawAtOffset(glImage* img, float pX, float pY, float oX, float oY, int flipMode); + void Update(float deltaTime); + void Draw(float fOffsetX, float fOffsetY); + static void CommonLoad(); +}; \ No newline at end of file diff --git a/source/Engine.h b/source/Engine.h new file mode 100644 index 0000000..ac55737 --- /dev/null +++ b/source/Engine.h @@ -0,0 +1,674 @@ +#ifndef DS_GAME_ENGINE_INCL +#define DS_GAME_ENGINE_INCL + +#include "EngineDec.h" +#include "Map.h" +#include + +/* +int round(float f){ + float decpt = f - (int)f; + if(decpt < 0.5f){ + return (int)f; + }else{ + return (int)f+1; + } +}*/ + +short screenbuffer_maindisplay[49152]; +short screen_width = 256; +short screen_height = 192; + +uint32_t input_keys = 0; +uint32_t input_keysUp = 0; +uint32_t input_keysDown = 0; +uint32_t input_keysHeld = 0; + +uint8_t GraphScreen; + +touchPosition touch; +touchPosition prevTouch; +PrintConsole bottomScreen; + +#define PlotPixel2(x,y,c) screenbuffer_maindisplay[(y)*256+(x)]=c + +bool GetKeyState(uint32_t button){ + uint32_t s = input_keys & button; + return s; +} +bool GetKeyDownState(uint32_t button){ + uint32_t s = input_keysDown & button; + return s; +} +bool GetKeyUpState(uint32_t button){ + uint32_t s = input_keysUp & button; + return s; +} +bool GetKeyHeldState(uint32_t button){ + uint32_t s = input_keysHeld & button; + return s; +} +/* +void PushFrame(){ + if(GraphScreen == SCREEN_BOTTOM) + { + dmaCopy(&screenbuffer_maindisplay, BG_GFX_SUB, 49152*2); + } + else + { + dmaCopy(&screenbuffer_maindisplay, BG_GFX, 49152*2); + } +} + +void SwitchScreenBottom() +{ + GraphScreen = SCREEN_TOP; + // Console is on bottom screen + videoSetMode(MODE_5_2D); + //videoSetModeSub(MODE_0_2D); + + vramSetBankA(VRAM_A_MAIN_BG); + //vramSetBankC(VRAM_C_SUB_BG); + + bgInit(2, BgType_Bmp16, BgSize_B16_256x256, 0,0); + + //consoleInit(&topScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true); + consoleInit(&bottomScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); + ClearScreen(0x0000); + PushFrame(); +} +void SwitchScreenTop() +{ + GraphScreen = SCREEN_BOTTOM; + // Console is on top screen + //videoSetModeSub(MODE_5_2D); + videoSetMode(MODE_0_2D); + + vramSetBankA(VRAM_A_MAIN_BG); + //vramSetBankC(VRAM_C_SUB_BG); + + //bgInitSub(2, BgType_Bmp16, BgSize_B16_256x256, 0,0); + + //consoleInit(&topScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true); + consoleInit(&bottomScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true); + ClearScreen(0x0000); + PushFrame(); +} + +void PlotPixel (int x, int y, short colour) +{ + if((x) >= 0 && (x) < 256 && (y) >= 0 && (y) < 192){ + screenbuffer_maindisplay[y*screen_width+x] = colour; + } +} + +void ClearScreen(short colour){ + for(int x = 0; x < 49152; x+=1){ + //PlotPixel(x % 256, x / 256, colour); + screenbuffer_maindisplay[x]=colour; + } +} + +void FillRectangle(short colour, int dx, int dy, int w, int h){ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + PlotPixel2(x+dx, dy+y, colour); + } + } + } +} +void FillRectangleLerp(short colour1, short colour2, int dx, int dy, int w, int h){ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + short colour = color_lerp(colour1, colour2, x * 255 / w); + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + PlotPixel2(x+dx, dy+y, colour); + } + } + } +} +void DrawRectangle(short colour, int dx, int dy, int w, int h){ + int x = 0; + for(x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256){ + PlotPixel2((x + dx), dy, colour); + } + } + for(x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256){ + PlotPixel2((x + dx), (dy - 1 + h), colour); + } + } + for(x = 0; x < h; x++){ + if((x+dx) >= 0 && (x+dx) < 256){ + PlotPixel2((dx), (x + dy), colour); + } + } + for(x = 0; x < h; x++){ + if((x+dx) >= 0 && (x+dx) < 256){ + PlotPixel2((w + dx - 1), (x + dy), colour); + } + } +} + +void DrawLine (int x1, int y1, int x2, int y2, short col){ + int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i; + dx = x2 - x1; dy = y2 - y1; + dx1 = abs(dx); dy1 = abs(dy); + px = 2 * dy1 - dx1; py = 2 * dx1 - dy1; + if (dy1 <= dx1) + { + if (dx >= 0) + { x = x1; y = y1; xe = x2; } + else + { x = x2; y = y2; xe = x1;} + + PlotPixel2(x, y, col); + + for (i = 0; x0 && dy>0)) y = y + 1; else y = y - 1; + px = px + 2 * (dy1 - dx1); + } + PlotPixel2(x, y, col); + } + } + else + { + if (dy >= 0) + { x = x1; y = y1; ye = y2; } + else + { x = x2; y = y2; ye = y1; } + + PlotPixel2(x, y, col); + + for (i = 0; y0 && dy>0)) x = x + 1; else x = x - 1; + py = py + 2 * (dx1 - dy1); + } + PlotPixel2(x, y, col); + } + } +} + +void DrawTriangle (int x1, int y1, int x2, int y2, int x3, int y3, short colour){ + DrawLine (x1, y1, x2, y2, colour); + DrawLine (x1, y1, x3, y3, colour); + DrawLine (x3, y3, x2, y2, colour); +} + +void FillTriangle (int x1, int y1, int x2, int y2, int x3, int y3, short col){ + / * Ripped from OneLoneCoder/ConsoleGameEngine * / + int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i; + dx = x2 - x1; dy = y2 - y1; + dx1 = abs(dx); dy1 = abs(dy); + px = 2 * dy1 - dx1; py = 2 * dx1 - dy1; + if (dy1 <= dx1) + { + if (dx >= 0) + { x = x1; y = y1; xe = x2; } + else + { x = x2; y = y2; xe = x1;} + + PlotPixel2(x, y, col); + DrawLine(x, y, x3, y3, col); + + for (i = 0; x0 && dy>0)) y = y + 1; else y = y - 1; + px = px + 2 * (dy1 - dx1); + } + PlotPixel2(x, y, col); + DrawLine(x, y, x3, y3, col); + } + } + else + { + if (dy >= 0) + { x = x1; y = y1; ye = y2; } + else + { x = x2; y = y2; ye = y1; } + + PlotPixel2(x, y, col); + DrawLine(x, y, x3, y3, col); + + for (i = 0; y0 && dy>0)) x = x + 1; else x = x - 1; + py = py + 2 * (dx1 - dy1); + } + PlotPixel2(x, y, col); + DrawLine(x, y, x3, y3, col); + } + } +} + +void DrawImageSizable(short* image, int w, int h, int dx, int dy, int dw, int dh){ + / *float pixel_width = dw / w; + float pixel_height= dh / h; + + for(int y = 0; y < dh; y++){ + for(int x = 0; x < dw; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + int src_y = round(y * pixel_height); + int src_x = round(x * pixel_width); + screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[(src_y*w+src_x)]; + } + } + }* / + + int w2 = dw, w1 = w, h2 = dh, h1 = h; + + // EDIT: added +1 to account for an early rounding problem + int x_ratio = (int)((w1<<16)/w2) +1; + int y_ratio = (int)((h1<<16)/h2) +1; + + int x2, y2 ; + for (int i=0;i>16) ; + y2 = ((i*y_ratio)>>16) ; + if((j+dx) >= 0 && (j+dx) < 256 && (i+dy) >= 0 && (i+dy) < 192){ + PlotPixel2(j+dx,i+dy,image[(y2*w1)+x2]); + } + } + } +} + +void DrawImage(short* image, int w, int h, int dx, int dy){ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + if(image[y*w+x] == -993){}else{ + PlotPixel2(x+dx,y+dy,image[y*w+x]); + } + } + } + } +} + +void DrawImageCrop(short* image, int w, int h, int dx, int dy, int sx, int sy, int dw, int dh){ + for(int y = 0; y < dh; y++){ + for(int x = 0; x < dw; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + if(image[(sy+y)*w+(sx+x)] == -993){}else{ + PlotPixel2(x+dx,y+dy,image[(sy+y)*w+(sx+x)]); + } + } + } + } +} + +void DrawImageCropFlipH(short* image, int w, int h, int dx, int dy, int sx, int sy, int dw, int dh){ + for(int y = 0; y < dh; y++){ + for(int x = 0; x < dw; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + if(image[(sy+y)*w+(sx+dw-1-x)] == -993){}else{ + PlotPixel2(x+dx,y+dy,image[(sy+y)*w+(sx+dw-1-x)]); + } + } + } + } +} + +void DrawImageFlippedV(short* image, int w, int h, int dx, int dy){ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + if(image[(h-y-1)*w+x] == -993){}else{ + PlotPixel2(x+dx,y+dy,image[(h-y-1)*w+x]); + } + } + } + } +} +void DrawImageFlippedHV(short* image, int w, int h, int dx, int dy){ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + if(image[(h-y)*w+(w-x-1)] == -993){}else{ + PlotPixel2(x+dx,y+dy,image[(h-y)*w+(w-x-1)]); + } + } + } + } +} +void DrawImageFlippedH(short* image, int w, int h, int dx, int dy){ + for(int y = 0; y < h; y++){ + for(int x = 0; x < w; x++){ + if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){ + if(image[y*w+(w-x-1)] == -993){}else{ + PlotPixel2(x+dx,y+dy,image[y*w+(w-x-1)]); + } + } + } + } +}*/ + +void PushFrame() { + glFlush(0); +} + +void PlotPixel(int x, int y, short color) { + // todo + glPutPixel(x, y, 0xffff); +} + +typedef struct { + union { + struct { + u8 r,g,b,a; + }; + u32 c; + }; +} color_t; + +inline float MapX(int x) { + double f = (double)x / 128.0 * .935; + f -= .935; + return (float)f; +} +inline float MapY(int y) { + double f = (191 - y) / 96.0 * .7; + f -= .7; + return (float)f; +} +color_t MakeColort(short color) { + color_t c; + c.r = (color & 0x1f) * 8; + c.g = ((color >> 5) & 0x3f) >> 2; + c.b = ((color >> 11) & 0x1f); + c.a = ((color & 0x8000) ? 31 : 0) << 3; + return c; +} + +void ClearScreen(short color) { + color_t c = MakeColort(color); + glClearColor(c.r, c.g, c.b, c.a); +} +#define fv floattov16 +void FillRectangle(short color, int dx, int dy, int w, int h) { + glBoxFilled(dx,dy,dx+w,dy+h,color); +} +void FillRectangleLerp(short co1, short co2, int dx, int dy, int w, int h) +{ + glBoxFilledGradient(dx,dy,dx+w,dy+h,co1,co1,co2,co2); +} +void DrawRectangle(short color, int dx, int dy, int w, int h) { + glBox(dx,dy,dx+w,dy+h,color); +} +void DrawLine(int x1, int y1, int x2, int y2, short col) { + glLine(x1,y1,x2,y2,MakeColort(col).c); +} +int GetGLTexSizeEnum(int w) { + /**/ if (w <= 8) return TEXTURE_SIZE_8; + else if (w <= 16) return TEXTURE_SIZE_16; + else if (w <= 32) return TEXTURE_SIZE_32; + else if (w <= 64) return TEXTURE_SIZE_64; + else if (w <= 128) return TEXTURE_SIZE_128; + else if (w <= 256) return TEXTURE_SIZE_256; + else if (w <= 512) return TEXTURE_SIZE_512; + else if (w <= 1024) return TEXTURE_SIZE_1024; + return TEXTURE_SIZE_1024; +} +int imageIDsReserved[TEXTURE_COUNT]; +int nextImageIdx; +int LoadImageVRAM(short* image, int w, int h) { + bool b = glTexImage2D(imageIDsReserved[nextImageIdx], 0, GL_RGBA, GetGLTexSizeEnum(w),GetGLTexSizeEnum(h), 0, 0, image); + LogMsg("Loading image with size %dx%d (it got id %d) was %s", w, h,imageIDsReserved[nextImageIdx], b ? "successful":"unsuccessful"); + return imageIDsReserved[nextImageIdx++]; +} +void FillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short colour) { + glTriangleFilled(x1,y1,x2,y2,x3,y3,colour); +} +void DrawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short colour) { + glTriangle(x1,y1,x2,y2,x3,y3,colour); +} +void DrawImageSizable(glImage* image, int w, int h, int dx, int dy, int dw, int dh){} +void SwitchScreenTop(){} +void SwitchScreenBottom(){} + +static v16 g_depth; +static inline void gxVertex3i_re(v16 x, v16 y, v16 z) +{ + GFX_VERTEX16 = (y << 16) | (x & 0xFFFF); + GFX_VERTEX16 = ((uint32)(uint16)z); +} +static inline void gxTexcoord2i_re(t16 u, t16 v) +{ + GFX_TEX_COORD = (v << 20) | ( (u << 4) & 0xFFFF ); +} +static inline void gxVertex2i_re(v16 x, v16 y) +{ + GFX_VERTEX_XY = (y << 16) | (x & 0xFFFF); +} +void DrawImageColored(glImage* spr, int w, int h, int dx, int dy, int flipmode, u16 color) { + // Cannot use glSprite, gotta recreate it + /* + int x1 = dx; + int y1 = dy; + int x2 = dx + spr->width; + int y2 = dy + spr->height; + + int u1 = spr->u_off + (( flipmode & GL_FLIP_H ) ? spr->width-1 : 0); + int u2 = spr->u_off + (( flipmode & GL_FLIP_H ) ? 0 : spr->width); + int v1 = spr->v_off + (( flipmode & GL_FLIP_V ) ? spr->height-1 : 0); + int v2 = spr->v_off + (( flipmode & GL_FLIP_V ) ? 0 : spr->height); + + + + if ( spr->textureID != gCurrentTexture ) + { + glBindTexture( GL_TEXTURE_2D, spr->textureID ); + gCurrentTexture = spr->textureID; + } + + glBegin( GL_QUADS ); + glColor(color);gxTexcoord2i_re( u1, v1 ); gxVertex3i_re( x1, y1, g_depth ); + glColor(color);gxTexcoord2i_re( u1, v2 ); gxVertex2i_re( x1, y2 ); + glColor(color);gxTexcoord2i_re( u2, v2 ); gxVertex2i_re( x2, y2 ); + glColor(color);gxTexcoord2i_re( u2, v1 ); gxVertex2i_re( x2, y1 ); + glEnd(); + g_depth++; + glColor(0x7FFF);*/ + glColor(color); + glSprite(dx, dy, flipmode, spr); + glColor(0x7FFF); +} +void DrawImageINT(glImage* image, int w, int h, int dx, int dy, int fm) { + glSprite(dx, dy, fm, image); +} +void DrawImageFlippedH (glImage* image, int w, int h, int dx, int dy) { + DrawImageINT(image, w, h, dx, dy, GL_FLIP_H); +} +void DrawImageFlippedHV(glImage* image, int w, int h, int dx, int dy) { + DrawImageINT(image, w, h, dx, dy, GL_FLIP_H|GL_FLIP_V); +} +void DrawImageFlippedV (glImage* image, int w, int h, int dx, int dy) { + DrawImageINT(image, w, h, dx, dy,GL_FLIP_V); +} +void DrawImage(glImage* image, int w, int h, int dx, int dy) { + DrawImageINT(image,w,h,dx,dy,0); +} +void DrawImageCrop(glImage* image, int w, int h, int dx, int dy, int sx, int sy, int dw, int dh) { + DrawImage(image, w, h, dx, dy); + //DrawRectangle(RED, dx, dy, dw, dh); +} +void DrawImageCropFlipH(glImage* image, int w, int h, int dx, int dy, int sx, int sy, int dw, int dh) { + DrawImageFlippedH(image, w, h, dx, dy); + //DrawRectangle(RED, dx, dy, dw, dh); +} +#undef fv +uint16_t GlobalTimer = 0; + +void OnUserCreate(); +void OnUserUpdate(); + +void InitConsoleScreen() {consoleSelect(&bottomScreen);} +void PrintChar(char x, char y, char c) { printf("\x1b[%d;%dH%c", y, x, c); } + +void DoEverySecond() { + LogMsg("test"); +} +int game_ticks = 0; +int millisSinceRun = 0; + +int fpsCounting, fps, prevS; + +#include "bmpfont.h" +short font_bmp[1024*8]; +int fontSpriteID; +glImage fontImage[128]; + +int main(void) { + //videoSetModeSub(MODE_5_2D); + lcdMainOnBottom(); + videoSetMode(MODE_5_3D); + videoSetModeSub(MODE_0_2D); + + // init gl2d + glScreen2D(); + glEnable(GL_ANTIALIAS); + vramSetBankA( VRAM_A_TEXTURE ); + vramSetBankB( VRAM_B_TEXTURE ); + + soundEnable(); + + bgInitSub(2, BgType_Bmp16, BgSize_B16_256x256, 0,0); + + consoleInit(&bottomScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); + + InitConsoleScreen(); + + timerStart(0, ClockDivider_1024, 0, NULL); + + glGenTextures(TEXTURE_COUNT, imageIDsReserved); + // load font shit + decompress(bmpfontBitmap,font_bmp,LZ77); + fontSpriteID = glLoadTileSet(fontImage, 6,8,1024,8, GL_RGBA, TEXTURE_SIZE_1024, TEXTURE_SIZE_8, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)font_bmp); + + OnUserCreate(); + while(1) { + glBegin2D(); + fpsCounting++; + game_ticks += timerElapsed(0); + uint64_t r = game_ticks * 1000llu; + r /= TIMER_SPEED; + millisSinceRun = r; + + int s = millisSinceRun / 1000; + if (prevS != s) { + fps = fpsCounting; + fpsCounting = 0; + } + prevS = s; + + prevTouch = touch; + touchRead(&touch); + scanKeys(); + + input_keys = keysCurrent(); + input_keysUp = keysUp(); + input_keysDown = keysDown(); + input_keysHeld = keysHeld(); + + OnUserUpdate(); + char str[100]; + memset(str,0,100); + sprintf(str, "fps: %d", fps); + DrawString(2, 184, BLACK, str, 0); + DrawString(1, 183, WHITE, str, 0); + + GlobalTimer++; + glEnd2D(); + PushFrame(); + g_depth = 4000; + swiWaitForVBlank(); + } + + return 0; +} + +bool RectangleContains(Rectangle r, Point p) { + return (r.x <= p.x && r.y <= p.y && r.x + r.width > p.x && r.y + r.height > p.y); +} + +bool RectangleIntersect(Rectangle r1, Rectangle r2) { + int playerX1 = r1.x, playerX2 = r1.x + r1.width, playerY1 = r1.y, playerY2 = r1.y + r1.height; + int tileRectX1 = r2.x, tileRectX2 = r2.x + r2.width, tileRectY1 = r2.y, tileRectY2 = r2.y + r2.height; + bool noOverlap = tileRectX1 > playerX2 || + playerX1 > tileRectX2 || + tileRectY1 > playerY2 || + playerY1 > tileRectY2; + return !noOverlap; +} + +/*int dx = x2 - x1; + int dy = y2 - y1; + + if (dx >= dy){ + float y = 0.0f; + if(x1 < x2){ + for (int x = x1; x <= x2; x++) { + y = y1 + dy * (x - x1) / dx; + PlotPixel(x, y, colour); + } + }else{ + for (int x = x2; x <= x1; x++) { + y = y1 + dy * (x - x1) / dx; + PlotPixel(x, y, colour); + } + } + }else{ + float x = 0.0f; + if(dx == 0){ + if(y1 < y2){ + for (int y = y1; y <= y2; y++) { + PlotPixel(x1, y, colour); + } + }else{ + for (int y = y2; y <= y1; y++) { + PlotPixel(x2, y, colour); + } + } + }else{ + if(y1 < y2){ + for (int y = y1; y <= y2; y++) { + x = x1 + dx * (y - y1) / dy; + PlotPixel(x, y, colour); + } + }else{ + for (int y = y2; y <= y1; y++) { + x = x1 + dx * (y - y1) / dy; + PlotPixel(x, y, colour); + } + } + } + }*/ + +#include "Features/RNG.h" +#include "Font.h" + +#endif diff --git a/source/EngineDec.h b/source/EngineDec.h new file mode 100644 index 0000000..0fe36e7 --- /dev/null +++ b/source/EngineDec.h @@ -0,0 +1,110 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + Programmed by iProgramInCpp + + EngineDec module +---------------------------------------------------------------------------------*/ +#ifndef ENGINEDEC_H +#define ENGINEDEC_H + +#include "Utils.hpp" +#include + +#define TIMER_SPEED (BUS_CLOCK/1024) + +// 16 bit color is structured in 1555 format +// EBGR +// E - enable bit / alpha +// RGBA16 + +#define WHITE 0xFFFF +#define BLACK 0x0000 +#define SKY 0xEEEF +#define BLUE 0xFC00 +#define MAGENTA 0xFC1F +#define CYAN 0xFFE0 +#define RED 0x801F +#define YELLOW 0x83FF + +//#define RGBA16(r,g,b,a) ((r << 11) | (g << 6) | (b << 1) | a) +#define RGBA16(r,g,b,a) ((a << 15) | (b << 10) | (g << 5) | r) +#define MakeColor5B(r,g,b) RGBA16(r,g,b,1) +#define MakeColor(r,g,b) RGBA16(r/8,g/8,b/8,1) + +#include +#include + +#define SCREEN_BOTTOM 1 +#define SCREEN_TOP 2 + +#define STYLE_BOLD 0x80 +#define STYLE_ITALIC 0x40 +#define STYLE_UNDERLINE 0x20 + +#define LAYER_FORE 0 +#define LAYER_BACK 1 + +#define TEXTURE_COUNT 16 +extern int imageIDsReserved[TEXTURE_COUNT]; + +bool GetKeyState(uint32_t button); +bool GetKeyDownState(uint32_t button); +bool GetKeyUpState(uint32_t button); +bool GetKeyHeldState(uint32_t button); +void PushFrame(); +void PlotPixel(int x, int y, short color); +void ClearScreen(short color); +void FillRectangle(short color, int dx, int dy, int w, int h); +void FillRectangleLerp(short c1, short c2, int dx, int dy, int w, int h); +void DrawRectangle(short color, int dx, int dy, int w, int h); +void DrawLine(int x1, int y1, int x2, int y2, short col); +void DrawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short colour); +void FillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short colour); +void DrawImageSizable(glImage* image, int w, int h, int dx, int dy, int dw, int dh); +void SwitchScreenTop(); +void SwitchScreenBottom(); +void DrawImageFlippedH (glImage* image, int w, int h, int dx, int dy); +void DrawImageFlippedHV(glImage* image, int w, int h, int dx, int dy); +void DrawImageFlippedV (glImage* image, int w, int h, int dx, int dy); +void PrintChar(char x, char y, char c); +void InitConsoleScreen(); +uint16_t map(uint16_t min, uint16_t max, uint8_t h); +uint16_t color_lerp(uint16_t min, uint16_t max, uint16_t i); +void DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint8_t styling); +void DrawString(uint8_t x, uint8_t y, uint16_t color, const char* str, uint8_t styling); +void DrawImage(glImage* image, int w, int h, int dx, int dy); +void DrawImageCrop(glImage* image, int w, int h, int dx, int dy, int sx, int sy, int dw, int dh); +void DrawImageCropFlipH(glImage* image, int w, int h, int dx, int dy, int sx, int sy, int dw, int dh); +void DrawImageColored(glImage* spr, int w, int h, int dx, int dy, int flipmode, u16 color); + +#define GetBlueComponent(i) (i & 0x7c00) >> 10 +#define GetGreenComponent(i) (i & 0x03e0) >> 5 +#define GetRedComponent(i) (i & 0x001f) + +#define Unite(r, g, b) 0x8000 | (b << 10) | (g << 5) | r + +extern touchPosition touch, prevTouch; +extern int fps; +extern uint16_t GlobalTimer; + +struct Rectangle { + int x, y, width, height; +}; +struct Point { + int x, y; +}; +typedef Point Point2d; +struct Point3d { + int x, y, z; +}; +struct Vec3f { + float x, y, z; +}; +struct Vec2f { + float x, y; +}; +bool RectangleContains(Rectangle r, Point p); +bool RectangleIntersect(Rectangle r1, Rectangle r2); + +#endif//ENDINEDEC_H \ No newline at end of file diff --git a/source/Features/RNG.h b/source/Features/RNG.h new file mode 100644 index 0000000..da56356 --- /dev/null +++ b/source/Features/RNG.h @@ -0,0 +1,22 @@ +unsigned short rng; + +short sky_colour = 0xEEEF; + +unsigned short rng_function(unsigned short input){ + if(input == 0x560A) input=0; + unsigned short S0 = (unsigned char)input<<8; + S0 = S0 ^ input; + input = ((S0 & 0xFF) << 8) | ((S0 & 0xFF00) >> 8); + S0 = ((unsigned char)S0 << 1) ^ input; + short S1 = (S0 >> 1) ^ 0xFF80; + if((S0 & 1) == 0){ + if(S1 == 0xAA55){input = 0;}else{input=S1 ^ 0x1FF4;} + }else{ + input = S1 ^ 0x1FF4; + } + return (unsigned short)input; +} + +void rng_update() { + rng = rng_function(GlobalTimer); +} diff --git a/source/Font.h b/source/Font.h new file mode 100644 index 0000000..df68e92 --- /dev/null +++ b/source/Font.h @@ -0,0 +1,77 @@ +#include "Typeface.h" +void DrawCharOld(uint16_t x, uint16_t y, char ch, uint16_t color, uint8_t styling) +{ + uint16_t address = ch * 5; + uint8_t n = 0; + uint16_t new_x = x + n; + uint16_t new_y; + uint8_t a; + uint16_t m = 4; + if((styling & STYLE_ITALIC) == 0) + { + m = 0; + } + for (n = 0; n < 5; n++) + { + new_x = x + n; + a = MainFont[address + n]; + if((styling & STYLE_ITALIC) != 0) + { + m = 4; + } + for(new_y = 0; new_y < 8; new_y++) + { + if(a & (0x01 << new_y)) + { + if((styling & STYLE_BOLD) != 0) + { + PlotPixel(new_x + m + 1, new_y + y, color); + } + PlotPixel(new_x + m, y + new_y, color); + } + if((styling & STYLE_ITALIC) != 0 && new_y % 3 == 0) { m--; } + } + if((styling & STYLE_UNDERLINE) != 0) + { + PlotPixel(new_x - 1, y + 7, color); + PlotPixel(new_x, y + 7, color); + PlotPixel(new_x + 1, y + 7, color); + } + } +} + +void DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint8_t styling) { + // italic and uline ignored for now, might add it later + if (ch >= 128) ch = 127; + DrawImageColored(&fontImage[(int)ch], 6, 8, x, y, 0, color); + if (styling & STYLE_BOLD) { + DrawImageColored(&fontImage[(int)ch], 6, 8, x+1, y, 0, color); + } +} +void DrawString(uint8_t x, uint8_t y, uint16_t color, const char* str, uint8_t styling) +{ + const char* m = str; + uint8_t ny = y; + uint8_t nx = x; + while(*m != 0) + { + if(*m == '\n') + { + nx = x; + ny += 8; + } + else + { + DrawChar(nx, ny, *m, color, styling); + if((styling & STYLE_BOLD) != 0) + { + nx += 7; + } + else + { + nx += 6; + } + } + m++; + } +} \ No newline at end of file diff --git a/source/Levels.inc.h b/source/Levels.inc.h new file mode 100644 index 0000000..134a53b --- /dev/null +++ b/source/Levels.inc.h @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + ProDrammed by iProDramInCpp + + Level include file +---------------------------------------------------------------------------------*/ +char level_1[] = + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "................................................................................................................................................................................................................................................................" + "..{S............................................................................................................................................................................................................................................................" + "GGGGGG.........................................................................................................................................................................................................................................................." + "GGGGGG.........................................................................................................................................................................................................................................................."; +char level_1_old[] = + "...................................................................................................................................................................................................oo............oo.........oo.................................." + ".......................................................................................oooooooooooo............................................................................................===================================.............................." + "............................?.................................................................................==?==..................................................................=========.........................................1!..................^...." + "....................................................................................BBBBBBBBBBBBBBBBBB.................................................................................................................................~`......................." + ".............................................................................................................................................................................=====....................................................=~`......................." + ".......................................................................................................................................................................................................................................~`......................." + "...^QAL..................BB?^?BB......................1!.......1!.............................................==^==......BB?BBBBBBB?BBBBBB?BB.......1!..............=====...............#.........................................??...~`....1!..........?.?.?.." + "...............................................1!.....~`.......~`................BBB........BBBBB...................................................~`..................................#.............................................=~`....~`......8.........." + "........................................1!.....~`.....~`.......~`...................................................................................~`......1!..........................#..............................................~`....~`................." + "..{S.(......&&...).......&......(...&...~`....)~`.....~`...(...~`............)..........(...&&........)...&.....&...(....&.....&....)......&.&.....(~`).....~`....)....&&.........(.....#...........................................(..~`....~`...&.&.&......).." + "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.....GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.........................................GGGGGGGGGGGGGGGGGGGGGGGGGGGG.." + "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD.....DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD.........................................DDDDDDDDDDDDDDDDDDDDDDDDDDDD.."; +int level_1_width = 256, level_1_height = 12; \ No newline at end of file diff --git a/source/Main.cpp b/source/Main.cpp new file mode 100644 index 0000000..f6d885c --- /dev/null +++ b/source/Main.cpp @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + Programmed by iProgramInCpp + + Main module +---------------------------------------------------------------------------------*/ +#include +#include +#include + +#include "Engine.h" +#include "Utils.hpp" +#include "TestGame.hpp" +/* + DS Game Engine Function Definitions + -- to keep in mind + + bool GetKeyState(uint32_t) + bool GetKeyDownState(uint32_t) + bool GetKeyUpState(uint32_t) + bool GetKeyHeldState(uint32_t) + void PushFrame(); + void PlotPixel(int x, int y, short color) + void ClearScreen(short color) + void FillRectangle(short color, int dx, int dy, int w, int h) + void FillRectangleLerp(short c1, short c2, int dx, int dy, int w, int h) + void DrawRectangle(short color, int dx, int dy, int w, int h) + void DrawLine(int x1, int y1, int x2, int y2, short col) + void DrawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short colour) + void FillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, short colour) + void DrawImageSizable(short* image, int w, int h, int dx, int dy, int dw, int dh) + void SwitchScreenTop() + void SwitchScreenBottom() + void DrawImageFlippedH(short* image, int w, int h, int dx, int dy) + void DrawImageFlippedHV(short* image, int w, int h, int dx, int dy) + void DrawImageFlippedV(short* image, int w, int h, int dx, int dy) + void PrintChar(char x, char y, char c); + void InitConsoleScreen(); +*/ +bool isFileSystemEnabled = false; +void OnUserCreate() +{ + /*isFileSystemEnabled = fatInitDefault(); + FILE* f = fopen("/test.txt", "r"); + char s [15]; + memset(s,0,15); + if (!f) { + LogMsg("Unable to open file"); + } else { + fread(s, 1, 14, f); + fclose(f); + LogMsg("Got string: %s", s); + }*/ + //SwitchScreenBottom(); + //SwitchScreenTop(); + //InitConsoleScreen(); + printf("\n\n\n\n\n\n\n\n"); + printf(" Growalone Maker V%.2f ", 0.10); // game version + printf(" For Nintendo DS / DSi "); + //printf(" This is intended for use with "); + //printf("the touch screen. Please look at"); + //printf(" the bottom screen now. "); + //printf(" There is NOTHING to see here..."); + printf("\n"); + printf("NOTE: You can't save. This is a "); + printf("prototype. Saving will be added "); + printf(" later.... "); + + Game::Init(); + Game::LoadContent(); +} + + +void OnUserUpdate() +{ + rng_update(); + //ClearScreen(RGBA16(0, 12, 31, 1)); + Game::Update(); +} diff --git a/source/Map.h b/source/Map.h new file mode 100644 index 0000000..9878940 --- /dev/null +++ b/source/Map.h @@ -0,0 +1,31 @@ + + +// returns an integer between min and max using range from 0-255 +uint16_t map(uint16_t min, uint16_t max, uint8_t h) +{ + uint16_t i = max - min; + if(h == 0x00) return min; + else if(h == 255) return max; + else + { + uint16_t m = min + (h * i / 256); + return m; + } +} + +uint16_t color_lerp(uint16_t min, uint16_t max, uint16_t i) +{ + uint8_t mred = GetRedComponent(min); + uint8_t mgreen = GetGreenComponent(min); + uint8_t mblue = GetBlueComponent(min); + + uint8_t m2red = GetRedComponent(max); + uint8_t m2green = GetGreenComponent(max); + uint8_t m2blue = GetBlueComponent(max); + + uint8_t rred = map(mred, m2red, i); + uint8_t rgreen = map(mgreen, m2green, i); + uint8_t rblue = map(mblue, m2blue, i); + + return Unite(rred, rgreen, rblue); +} \ No newline at end of file diff --git a/source/TestGame.cpp b/source/TestGame.cpp new file mode 100644 index 0000000..43df9b3 --- /dev/null +++ b/source/TestGame.cpp @@ -0,0 +1,1427 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + Programmed by iProgramInCpp + + TestGame module +---------------------------------------------------------------------------------*/ + +#include "TestGame.hpp" +#include +#include +#include +#include +#include "character.h" +#include "tiles.h" +#include "clapperboard.h" +#include "undo.h" +#include "reset.h" +#include "erase.h" +#include "itemsel.h" +#include "item.h" +#include "lr_arrows.h" +#include "erase_mode.h" +#include "copy_mode.h" +#include "dialog_bg.h" +#include "dialogbtn.h" +#include "logo.h" +#include "Enemy.hpp" + +// todo: add save +/* +short tiles[128*128]; +short character[128*16]; +short clapperboard[128*64]; +short undoBmp[32*32]; +short eraseBmp[32*32]; +short lrArrowsBmp[32*32]; +short resetBmp[32*32]; +short itemSelBmp[32*32]; +short itemBmp[32*32]; +short ermodBmp[64*16]; +*/ + +short textureCacheBmp[256*256]; +bool hasPressedLROrStart = false; + + +bool isInCopyMode = false; +bool isDraggingStuff = false; +float worldDragPosX, worldDragPosY; +float lastWorldTouchPosX, lastWorldTouchPosY; +int draggedRectX1 = -1, draggedRectY1; +int draggedRectX2 = -1, draggedRectY2; + +#include "Levels.inc.h" + +char* sLevel, *sLevelBeforePlay; +int nLevelWidth, nLevelHeight; + +bool bPlayerOnGround = false; + +int nDirModX = 0, nDirModY = 0; + +float fCameraPosX = 0.0f, fCameraPosY = 0.0f; +float fPlayerPosX = 0.0f, fPlayerPosY = 0.0f; +float fPlayerVelX = 0.0f, fPlayerVelY = 0.0f; + +glImage tilesImage[64]; +glImage playrImage[9]; +glImage cbordImage[2]; +glImage resetImage[1]; +glImage eraseImage[1]; +glImage itemSImage[1]; +glImage itemImage[1]; +glImage lrArrowImage[2]; +glImage undoImage[1]; +glImage ermodImage[1]; +glImage cpmodImage[1]; +glImage dlgBgImage[1]; +glImage dlgBtnImage[1]; +glImage logoImage[1]; +int tileSpriteID, plyrSpriteID, cbrdSpriteID; +int lrArSpriteID; +int resetSpriteID; +int eraseSpriteID; +int itemSelSpriteID; +int itemSpriteID; +int undoSpriteID; +int ermodSpriteID; +int cpmodSpriteID; +int dlgBgSpriteID; +int dlgBtnSpriteID; +int logoSpriteID; + +enum GameMode { + Mode_Game, + Mode_Title, + Mode_Maker +}; +int gameMode = Mode_Title; + +const char* dialogRow1, *dialogRow2, *dialogRow3, *dialogYesText, *dialogNoText; +DialogResultFunction *dialogResultFunc; +bool dialogShown; +int dialogPosition = 192; + +void ShowDialog(DialogResultFunction* f, const char* dialogYes, const char* dialogNo, const char* dlgRow1, const char* dlgRow2, const char* dlgRow3) { + dialogYesText = dialogYes; + dialogNoText = dialogNo; + dialogRow1 = dlgRow1; + dialogRow2 = dlgRow2; + dialogRow3 = dlgRow3; + dialogResultFunc = f; + dialogShown = true; + dialogPosition = 192; +} + +void ResetLevel(bool yes); + +bool dialogButtonsClicked[2]; + +void DrawDialog(bool processTouch = true) { + DrawImage(dlgBgImage, 256, 192, 0, dialogPosition); + Rectangle rBtn[2] = { + { 20, 136, 96, 32 }, + { 138, 136, 96, 32 } + }; + + // draw text + int m = dialogPosition; + m += 50; + DrawString((SCREEN_WIDTH - strlen(dialogRow1) * 6) / 2, m, BLACK, dialogRow1, 0); + m += 9; + DrawString((SCREEN_WIDTH - strlen(dialogRow2) * 6) / 2, m, BLACK, dialogRow2, 0); + m += 9; + DrawString((SCREEN_WIDTH - strlen(dialogRow3) * 6) / 2, m, BLACK, dialogRow3, 0); + + bool clicked[2] = { 0, 0 }; + Point pTouch = { touch.px, touch.py }; + for (int i = 0; i < 2; i++) { + uint16_t color = 0xFFFF; + rBtn[i].y += dialogPosition; + if (processTouch) { + if (RectangleContains(rBtn[i], pTouch)) { + color &= 0xbdef; + clicked[i] = true; + } + } + DrawImageColored(dlgBtnImage, 128, 32, rBtn[i].x, rBtn[i].y, 0, color); + } + DrawString((96 - strlen(dialogNoText) * 6) / 2 + rBtn[0].x, rBtn[0].y + 12, BLACK, dialogNoText, 0); + DrawString((96 - strlen(dialogYesText) * 6) / 2 + rBtn[1].x, rBtn[1].y + 12, BLACK, dialogYesText, 0); + if (processTouch) { + for (int i = 0; i < 2; i++) { + if (!clicked[i] && dialogButtonsClicked[i]) { + ResetLevel(i); + dialogShown = false; + } + } + memcpy(dialogButtonsClicked, clicked, sizeof(clicked)); + } +} + +char GetTile(int x, int y){ + int cy = y; + if (y < 0) y = 0; + if(x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight){ + if (cy < y && sLevel[y*nLevelWidth+x] == 'o') return '.'; + return sLevel[y*nLevelWidth+x]; + }else{ + return ' '; + } +} + +void SetTile(char c, int x, int y){ + if(x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight){ + sLevel[y*nLevelWidth+x] = c; + } +} + +int GetDirModX() { + return nDirModX; +} +const char* makeText = "Make", *playText = "Play"; +bool hasClickedPreviously[2]; + +// enemy list +std::vector> enemies; + +float maxTime = 500; +int gems = 0, score = 0; +float inGameTime = maxTime; +bool isOnOffSwitchOn = true; +bool CanBeBumped(char c) { + switch (c) { + case '?': + case '^': + case 'Q': + case 'A': + case 'L': + case 'B': + case 'E': + return true; + } + return false; +} +bool ending = false; +int endingStage = 0; +bool IsSolid(char c, int directions) { + switch (c) { + case 'o': + case '(': + case ')': + case '{': + case '}': + case '&': + case '.': + case ' ': + case 'S': + case '0': + case '8': + return false; + case '=': + if (directions & DIR_DOWN) return true; + return false; + case 'F': + return !isOnOffSwitchOn; + case 'H': + return isOnOffSwitchOn; + default: + return true; + } +} + +void SpawnEnemy(const Enemy enemy) { + if (enemies.size() >= 100) { + //LogMsg("Enemy limit reached"); + return; + } + auto u = std::make_unique(enemy); + enemies.push_back(std::move(u)); +} + +void SpawnMushTypeRise(float x, float y, int type) { + Enemy mush; + mush.type = type; + mush.posX = mush.homeX = floorf(x); mush.posY = mush.homeY = floorf(y); + mush.mushroom.risingTimer = 1.0f; + SpawnEnemy(mush); +} + +int hp = 1, maxHP = 1; +float lastHP = 0.0f; +void IncreaseMaxHP() { + maxHP++; + hp = maxHP; +} + +void AddToMaxHP(int i) { + while (i > 0) { + IncreaseMaxHP(); + i--; + } +} + +#define State_Idle 0 +#define State_Jump 1 +#define State_Walk 2 +#define State_Run 3 +#define State_Skid 4 +#define State_Dead 5 +#define State_Crouch 6 +int playerState = State_Idle; + +float gameTimer = 0; +float deathTimer = 0.0f; +bool canEditLevel = false; +int dieStage = 0; +bool doPlayerFallAfterDeath = false; + +void ResetEverything(); +void KillPlayer(bool doInstantly) { + // play jingle, then wait a few seconds + deathTimer = 0.0f; + playerState = State_Dead; + dieStage = 0; + doPlayerFallAfterDeath = !doInstantly; + fPlayerVelY = fPlayerVelX = 0; +} +void LoadLevelToMem(char* c, int w, int h); +void DoLevelInitStuff(); + +bool doSetToMakerMode = false; + +float stunTimer = 0.0f; + +void DamagePlayer() { + if (stunTimer > 0.0f) return; + hp--; + if (hp <= 0) { + hp = 0; + KillPlayer(false); + return; + } + stunTimer = 4.0f; +} +void HealPlayer() { + hp++; + while (hp > maxHP) { + maxHP++; + } +} + +float BlockBumpTimer = 0.0f; +int BlockBumpedX = -1, BlockBumpedY = -1; +float endingTimer = 0; +void ResetEverything() { + isOnOffSwitchOn = true; + memcpy(sLevel, sLevelBeforePlay, nLevelHeight * nLevelWidth); + enemies.clear(); + hp = 1; + maxHP = 1; + inGameTime = 500; + gems = 0; + score = 0; + stunTimer = 0; + lastHP = 1; + ending = false; + endingStage = 0; + endingTimer = 0; +} +void SetToMakerMode() { + doSetToMakerMode = true; + BlockBumpTimer = 0.0f; + BlockBumpedX = BlockBumpedY = -1; + ResetEverything(); +} + +void SpawnBump(int x, int y) { + if (!CanBeBumped(GetTile(x,y))) return; + BlockBumpTimer = 0.0f; + BlockBumpedX = x; + BlockBumpedY = y; +} +void ResetLevel(bool yes) { + if (!yes) return; + //gameMode = Mode_Maker; + SetToMakerMode(); + LoadLevelToMem(level_1, level_1_width, level_1_height); + canEditLevel = true; +} + +void Game::UpdateGameLogic(float fElapsedTime) { + gameTimer += fElapsedTime; + stunTimer -= fElapsedTime; + if (stunTimer < 0) stunTimer = 0; + if (inGameTime >= -1 && playerState != State_Dead && !ending) { + inGameTime -= fElapsedTime; + } + if (inGameTime < 0 && !ending) { + inGameTime = 0; + KillPlayer(false); + } + /* + if (GetKeyState(KEY_UP)) { + fPlayerVelY = -6.0f; + } + if (GetKeyState(KEY_DOWN)) { + fPlayerVelY = 6.0f; + }*/ + + BlockBumpTimer += fElapsedTime; + if (BlockBumpTimer > .25f) { + BlockBumpTimer = 0.0f; + BlockBumpedX = BlockBumpedY = -1; + } + + if (gameMode == Mode_Game) { + if (canEditLevel) { + if (GetKeyDownState(KEY_SELECT) || GetKeyDownState(KEY_START)) { + SetToMakerMode(); + } + } + } + + if (endingStage == 1) { + if (inGameTime >= 10) { + inGameTime -= 10; + score += 100; + } + if (inGameTime >= 1) { + inGameTime--; + score += 10; + } else { + endingStage++; + endingTimer = 3; + } + } + if (endingStage == 2) { + endingTimer -= fElapsedTime; + if (endingTimer <= 0.0f) { + if (canEditLevel) { + SetToMakerMode(); + } + ResetEverything(); + DoLevelInitStuff(); + } + } + + if (playerState == State_Dead) { + deathTimer += fElapsedTime; + if (deathTimer >= 1.0f && doPlayerFallAfterDeath) { + if (dieStage == 0) { + dieStage++; + fPlayerVelY = -12.0f; + } else { + fPlayerVelY += 20.0f * fElapsedTime; + } + } + fPlayerPosX += fPlayerVelX * fElapsedTime; + fPlayerPosY += fPlayerVelY * fElapsedTime; // no collision + if (deathTimer >= 5.0f) { + if (canEditLevel) { + SetToMakerMode(); + } + ResetEverything(); + DoLevelInitStuff(); + } + } else { + if (fPlayerPosY > nLevelHeight + 3.0f) { + KillPlayer(true); + } + float addSpeed = 6.0f; + bool holdingRun = false; + if(GetKeyState(KEY_Y) || GetKeyState(KEY_X)){ + addSpeed += 8.0f; + holdingRun = true; + } + + float groundFriction = 6.0f; + bool hitDirKey = false; + if (!ending) { + if (playerState == State_Crouch) playerState = State_Idle; + if(GetKeyState(KEY_DOWN)){ + playerState = State_Crouch; + } + if(GetKeyState(KEY_LEFT) && playerState != State_Crouch){ + hitDirKey = true; + bool isSkidding = false; + if (playerState == State_Idle || playerState == State_Walk || playerState == State_Run || playerState == State_Skid) { + if (fPlayerVelX > 0) { + playerState = State_Skid; + isSkidding = true; + } else { + playerState = holdingRun ? State_Run : State_Walk; + } + } + if (bPlayerOnGround && !isSkidding) nDirModY = 1; + fPlayerVelX += -addSpeed * fElapsedTime; + groundFriction = 2.0f; + } + if(GetKeyState(KEY_RIGHT) && playerState != State_Crouch){ + hitDirKey = true; + bool isSkidding = false; + if (playerState == State_Idle || playerState == State_Walk || playerState == State_Run || playerState == State_Skid) { + if (fPlayerVelX < 0) { + playerState = State_Skid; + isSkidding = true; + } else { + playerState = holdingRun ? State_Run : State_Walk; + } + } + if (bPlayerOnGround && !isSkidding) nDirModY = 0; + fPlayerVelX += addSpeed * fElapsedTime; + groundFriction = 2.0f; + } + if (!hitDirKey && (playerState == State_Walk || playerState == State_Run || playerState == State_Skid) && bPlayerOnGround) playerState = State_Idle; + if (playerState == State_Jump && bPlayerOnGround) playerState = State_Idle; + if ((GetKeyDownState(KEY_B) || GetKeyDownState(KEY_A)) && playerState != State_Crouch) { + if(bPlayerOnGround){ + playerState = State_Jump; + fPlayerVelY = -14.0f; + nDirModX = 1; + } + } + if (GetKeyDownState(KEY_SELECT)) { + //KillPlayer(false); + } + } else { + // go right + if (endingStage == 0 && bPlayerOnGround) { + fPlayerVelX = 7; + playerState = State_Run; + } + } + fPlayerVelY += 20.0f * fElapsedTime; + + if (bPlayerOnGround) { + fPlayerVelX += -groundFriction * fPlayerVelX * fElapsedTime; + if(fabs(fPlayerVelX) < 0.01f){ + fPlayerVelX = 0.0f; + } + } + + if (fPlayerVelX > 10.0f) fPlayerVelX = 10.0f; + if (fPlayerVelX < -10.0f) fPlayerVelX = -10.0f; + if (fPlayerVelY > 100.0f) fPlayerVelY = 100.0f; + if (fPlayerVelY < -100.0f) fPlayerVelY = -100.0f; + bPlayerOnGround = false; + for (int i = 0; i < 5; i++) { + float fNewPlayerPosX = fPlayerPosX + fPlayerVelX * fElapsedTime * .2f; + float fNewPlayerPosY = fPlayerPosY + fPlayerVelY * fElapsedTime * .2f; + if (fNewPlayerPosX < 0) fNewPlayerPosX = 0; + if (ending) { + if (fNewPlayerPosX >= nLevelWidth) { + fNewPlayerPosX = nLevelWidth; + if (endingStage == 0) endingStage++; + fPlayerVelX = 0; + } + } else { + if (fNewPlayerPosX >= nLevelWidth - 1) { + fNewPlayerPosX = nLevelWidth - 1; + } + } + + if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f) == 'o') + { SetTile('.', fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f); gems++; score += 100; } + if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f) == 'o') + { SetTile('.', fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f); gems++; score += 100; } + if (GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f) == 'o') + { SetTile('.', fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f); gems++; score += 100; } + if (GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f) == 'o') + { SetTile('.', fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f); gems++; score += 100; } + + if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f) == '8') + { SetTile('0', fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f); ending = true; endingStage = 0; fPlayerVelX = 0; } + if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f) == '8') + { SetTile('0', fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f); ending = true; endingStage = 0; fPlayerVelX = 0; } + if (GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f) == '8') + { SetTile('0', fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f); ending = true; endingStage = 0; fPlayerVelX = 0; } + if (GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f) == '8') + { SetTile('0', fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f); ending = true; endingStage = 0; fPlayerVelX = 0; } + + + //Collision + if(fPlayerVelX < 0){ + if (IsSolid(GetTile(fNewPlayerPosX + 0.0f, fPlayerPosY + 0.0f), DIR_LEFT) || + IsSolid(GetTile(fNewPlayerPosX + 0.0f, fPlayerPosY + 0.9f), DIR_LEFT)){ + fNewPlayerPosX = (int)fNewPlayerPosX + 1; + fPlayerVelX = 0; + } + } + else if (fPlayerVelX > 0) { + if (IsSolid(GetTile(fNewPlayerPosX + 1.0f, fPlayerPosY + 0.0f), DIR_RIGHT) || + IsSolid(GetTile(fNewPlayerPosX + 1.0f, fPlayerPosY + 0.9f), DIR_RIGHT)){ + fNewPlayerPosX = (int)fNewPlayerPosX; + fPlayerVelX = 0; + if (ending) { + if (endingStage == 0) endingStage++; // initializes the countdown etc + playerState = State_Crouch; + nDirModY = 1; + } + } + } + + if (fPlayerVelY < 0) { + char c1 = GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY), c2 = GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + bool s1 = IsSolid(c1, DIR_UP); + bool s2 = IsSolid(c2, DIR_UP); + if (s1 || s2){ + if (nDirModY) { + if (s2) { + SpawnBump(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + if (c2 == '?') { gems++; score += 100; SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); } + if (c2 == '^') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_Mushroom); } + if (c2 == 'Q') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_Flower); } + if (c2 == 'A') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_Time); } + if (c2 == 'L') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_LifeUp); } + if (c2 == 'E') { isOnOffSwitchOn ^= 1;} + c1 = GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY); c2 = GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + } + if (s1) { + SpawnBump(fNewPlayerPosX + 0.0f, fNewPlayerPosY); + if (c1 == '?') { gems++; score += 100; SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); } + if (c1 == '^') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_Mushroom); } + if (c1 == 'Q') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_Flower); } + if (c1 == 'A') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_Time); } + if (c1 == 'L') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_LifeUp); } + if (c1 == 'E' && c2 != 'E') { isOnOffSwitchOn ^= 1;} + c1 = GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY); c2 = GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + } + } + else { + if (s1) { + SpawnBump(fNewPlayerPosX + 0.0f, fNewPlayerPosY); + if (c1 == '?') { gems++; score += 100; SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); } + if (c1 == '^') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_Mushroom); } + if (c1 == 'Q') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_Flower); } + if (c1 == 'A') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_Time); } + if (c1 == 'L') { SetTile('U', fNewPlayerPosX + 0.0f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.0f, fNewPlayerPosY - .5f, Enemy_LifeUp); } + if (c1 == 'E') { isOnOffSwitchOn ^= 1;} + c1 = GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY); c2 = GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + } + if (s2) { + SpawnBump(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + if (c2 == '?') { gems++; score += 100; SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); } + if (c2 == '^') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_Mushroom); } + if (c2 == 'Q') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_Flower); } + if (c2 == 'A') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_Time); } + if (c2 == 'L') { SetTile('U', fNewPlayerPosX + 0.9f, fNewPlayerPosY); SpawnMushTypeRise(fNewPlayerPosX + 0.9f, fNewPlayerPosY - .5f, Enemy_LifeUp); } + if (c2 == 'E' && c1 != 'E') { isOnOffSwitchOn ^= 1;} + c1 = GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY); c2 = GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY); + } + } + fNewPlayerPosY = (int)fNewPlayerPosY + 1; + fPlayerVelY = 0; + } + } + else if (fPlayerVelY > 0) { + if (IsSolid(GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY+1), DIR_DOWN) || + IsSolid(GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY+1), DIR_DOWN)){ + fNewPlayerPosY = (int)fNewPlayerPosY; + fPlayerVelY = 0; + bPlayerOnGround = true; + nDirModX = 0; + } + } + fPlayerPosX = fNewPlayerPosX; + fPlayerPosY = fNewPlayerPosY; + } + // update enemies + for (uint32_t i = 0; i < enemies.size(); i++) { + enemies.at(i)->Update(fElapsedTime); + } +begin_deleting_shit: + for (uint32_t i = 0; i < enemies.size(); i++) { + if (enemies.at(i)->markForRemoval) { + // here we have the mark for removal shit, remove + // and restart the loop (not most efficient but it will do! + enemies.erase(enemies.begin() + i); + goto begin_deleting_shit; + } + } + } + switch (playerState) { + case State_Idle: nDirModX = 0; break; + case State_Walk: { + int r = (int)(gameTimer * 48.f); // every second represents 48 ticks, caps at 24 (.5s) + r %= 24; + nDirModX = 2 + r / 8; + break; + } + case State_Run: { + int r = (int)(gameTimer * 24.f); // every second represents 24 ticks, caps at 6 (.25s) + r %= 6; + nDirModX = 2 + r / 2; + break; + } + case State_Jump: nDirModX = 1; break; + case State_Skid: nDirModX = 5; break; + case State_Dead: nDirModX = 6; break; + case State_Crouch: nDirModX = 7; break; + } + while (gameTimer > 2048) { + gameTimer -= 2048.f; + } + fCameraPosX = fPlayerPosX + .5f; + fCameraPosY = fPlayerPosY + .5f; + +} +void DrawTile(char sTileID, int x, int y, char sTileIDAbove, bool renderInInventory, int tileX, int tileY) { + //^QAS + switch(sTileID){ + case '.': break; + case '#':DrawImage(&tilesImage[2], 16, 16,x, y);break; + case 'o':DrawImage(&tilesImage[3], 16, 16,x, y);break; + case '?':DrawImage(&tilesImage[9], 16, 16,x, y);break; + case '^':DrawImage(&tilesImage[gameMode == Mode_Maker ? 41 : 9], 16, 16,x, y); break; + case 'Q':DrawImage(&tilesImage[gameMode == Mode_Maker ? 44 : 9], 16, 16,x, y); break; + case 'A':DrawImage(&tilesImage[gameMode == Mode_Maker ? 45 : 9], 16, 16,x, y); break; + case 'L':DrawImage(&tilesImage[gameMode == Mode_Maker ? 46 : 9], 16, 16,x, y); break; + case 'B':DrawImage(&tilesImage[8], 16, 16,x, y);break; + case 'G': { + if (sTileIDAbove == 'G') + DrawImage(&tilesImage[0], 16, 16,x, y); + else + DrawImage(&tilesImage[16], 16, 16,x, y); + break; + } + case 'P': { + if (sTileIDAbove == 'P') + DrawImage(&tilesImage[35], 16, 16,x, y); + else + DrawImage(&tilesImage[34], 16, 16,x, y); + break; + } + case 'D':DrawImage(&tilesImage[0], 16, 16,x, y);break; + case 'U':DrawImage(&tilesImage[1], 16, 16,x, y);break; + case '1':DrawImage(&tilesImage[18], 16, 16,x, y);break; + case '!':DrawImage(&tilesImage[19], 16, 16,x, y);break; + case '~':DrawImage(&tilesImage[20], 16, 16,x, y);break; + case '`':DrawImage(&tilesImage[21], 16, 16,x, y);break; + case '(':DrawImage(&tilesImage[4], 16, 16,x, y);break; + case ')':DrawImage(&tilesImage[5], 16, 16,x, y);break; + case '|': { + if (sTileIDAbove == '|') + DrawImage(&tilesImage[7], 16, 16,x, y); + else + DrawImage(&tilesImage[6], 16, 16,x, y); + break; + } + case 'S': + if (gameMode == Mode_Maker) { + DrawImage(&tilesImage[13], 16, 16,x, y);break; + } else return; + case '{':DrawImage(&tilesImage[12], 16, 16,x, y);break; + case '}':DrawImage(&tilesImage[10], 16, 16,x, y);break; + case '&':DrawImage(&tilesImage[11], 16, 16,x, y);break; + case '=':DrawImage(&tilesImage[24], 16, 16,x, y);break; + case '>':DrawImage(&tilesImage[22], 16, 16,x, y);break; + case 'E':DrawImage(&tilesImage[isOnOffSwitchOn?25:26], 16, 16,x, y);break; + case 'F':DrawImage(&tilesImage[isOnOffSwitchOn?27:29], 16, 16,x, y);break; + case 'H':DrawImage(&tilesImage[isOnOffSwitchOn?30:28], 16, 16,x, y);break; + case '0':DrawImage(&tilesImage[52], 16, 16,x, y);break; + case '8':{ + // Draw the end marker + int frame = (int)(gameTimer * 8) % 4; + DrawImage(&tilesImage[48 + frame], 16, 16, x, y); + break; + } + case 'W': { + // spawn flower + if (renderInInventory || gameMode == Mode_Maker) { + DrawImage(&tilesImage[36], 16, 16,x, y); + } else { + Enemy mush; + mush.type = Enemy_Flower; + mush.posX = tileX; mush.posY = tileY; mush.homeX = 0; mush.homeY = 0; mush.mushroom.risingTimer = 0.0f; + SpawnEnemy(mush); SetTile('.', tileX, tileY); DrawTile('.', x, y, sTileIDAbove, renderInInventory); + } + break; + } + case 'X': { + // spawn life up + if (renderInInventory || gameMode == Mode_Maker) { + DrawImage(&tilesImage[38], 16, 16,x, y); + } else { + Enemy mush; + mush.type = Enemy_LifeUp; + mush.posX = tileX; mush.posY = tileY; mush.homeX = 0; mush.homeY = 0; mush.mushroom.risingTimer = 0.0f; + SpawnEnemy(mush); SetTile('.', tileX, tileY); DrawTile('.', x, y, sTileIDAbove, renderInInventory); + } + break; + } + case 'T': { + // spawn extra clock? + if (renderInInventory || gameMode == Mode_Maker) { + DrawImage(&tilesImage[37], 16, 16,x, y); + } else { + Enemy mush; + mush.type = Enemy_Time; + mush.posX = tileX; mush.posY = tileY; mush.homeX = 0; mush.homeY = 0; mush.mushroom.risingTimer = 0.0f; + SpawnEnemy(mush); SetTile('.', tileX, tileY); DrawTile('.', x, y, sTileIDAbove, renderInInventory); + } + break; + } + case 'M': { + // spawn mushroom? + if (renderInInventory || gameMode == Mode_Maker) { + DrawImage(&tilesImage[33], 16, 16,x, y); + } else { + Enemy mush; + mush.type = Enemy_Mushroom; + mush.posX = tileX; mush.posY = tileY; mush.homeX = 0; mush.homeY = 0; mush.mushroom.risingTimer = 0.0f; + SpawnEnemy(mush); SetTile('.', tileX, tileY); DrawTile('.', x, y, sTileIDAbove, renderInInventory); + } + break; + } + default: DrawImage(&tilesImage[63], 16, 16,x, y);break; + //FillRectangle(RGBA16(0, 12, 31, 1), x, y, 16, 16); + //break; + } +} + +bool isInEraseMode = false; +bool isDrawing = false; +bool multigrabMode = false; // unused, todo +void Game::Draw() { + + //Draw Level + int nTileWidth = 16; + int nTileHeight = 16; + int nVisibleTilesX = SCREEN_WIDTH / nTileWidth; + int nVisibleTilesY = SCREEN_HEIGHT/nTileHeight; + + float fOffsetX = fCameraPosX - (float)nVisibleTilesX / 2.0f; + float fOffsetY = fCameraPosY - (float)nVisibleTilesY / 2.0f; + + if(fOffsetX <= 0.0f) fOffsetX = 0.0f; + if(fOffsetY <= 0.0f) fOffsetY = 0.0f; + if(fOffsetX > (float)(nLevelWidth - nVisibleTilesX)) fOffsetX = nLevelWidth - nVisibleTilesX; + if(fOffsetY > (float)(nLevelHeight- nVisibleTilesY)) fOffsetY = nLevelHeight- nVisibleTilesY; + + float fTileOffsetX = (fOffsetX - (int)fOffsetX) * nTileWidth; + float fTileOffsetY = (fOffsetY - (int)fOffsetY) * nTileHeight; + + + for(int x = 0; x <= nVisibleTilesX; x++){ + for(int y = 0; y <= nVisibleTilesY; y++){ + int tileX = floorf((float)x + fOffsetX), tileY = floorf((float)y+fOffsetY); + char sTileID = GetTile(tileX, tileY); + char sTileIDAbove = GetTile(tileX, tileY - 1); + int BumpedBlockDrawY = 0; + if (tileX == BlockBumpedX && tileY == BlockBumpedY) { + BumpedBlockDrawY = (int)(sinf(BlockBumpTimer * 12.f) * -8.f); + } + bool shouldDraw = true; + if (gameMode == Mode_Maker) + { + Rectangle r1 = { draggedRectX1, draggedRectY1, draggedRectX2 - draggedRectX1 + 1, draggedRectY2 - draggedRectY1 + 1 }; + Point p = { tileX, tileY }; + shouldDraw = !isDraggingStuff || !RectangleContains(r1,p) || isInCopyMode; + } + if (shouldDraw) + DrawTile(sTileID, x*nTileWidth-fTileOffsetX, y*nTileHeight-fTileOffsetY + BumpedBlockDrawY, sTileIDAbove, false, tileX, tileY); + } + } + + if (multigrabMode) { + int px1 = (draggedRectX1 - fOffsetX) * nLevelWidth; + int py1 = (draggedRectY1 - fOffsetY) * nLevelWidth; + int px2 = (draggedRectX2 - fOffsetX) * nLevelWidth; + int py2 = (draggedRectY2 - fOffsetY) * nLevelWidth; + DrawRectangle(YELLOW, px1, py1, px2, py2); + } + + // draw the dragged tiles? + if (isDraggingStuff) { + for(int x = draggedRectX1; x <= draggedRectX2; x++){ + for(int y = draggedRectY1; y <= draggedRectY2; y++){ + int posX = ((float)x + (float)worldDragPosX / (float)nTileWidth - (float)draggedRectX1 - fOffsetX) * nTileWidth; + int posY = ((float)y + (float)worldDragPosY / (float)nTileWidth - (float)draggedRectY1 - fOffsetY) * nTileHeight; + DrawTile(GetTile(x, y), posX, posY, '.', false, x, y); + } + } + } + + bool doDisplayChar = true; + if (stunTimer > 0) { + doDisplayChar = GlobalTimer % 2; + } + if (doDisplayChar) { + if (nDirModY) + DrawImageFlippedH(&playrImage[nDirModX], nTileWidth, nTileHeight, (fPlayerPosX - fOffsetX)*nTileWidth, (fPlayerPosY - fOffsetY)*nTileHeight); + else + DrawImage(&playrImage[nDirModX], nTileWidth, nTileHeight, (fPlayerPosX - fOffsetX)*nTileWidth, (fPlayerPosY - fOffsetY)*nTileHeight); + } + for (uint32_t i = 0; i < enemies.size(); i++) { + enemies.at(i)->Draw(fOffsetX, fOffsetY); + } +} +bool hasInventoryOpen = false; +bool hasRightMenuOpen = false; +bool hasClickedPreviouslyMaker[15]; + +char hotbarSlots[8]; +int inventoryHotbarSelectedIdx = 0; +int hotbarSlotPage = 0; + +#define HOTBAR_SLOT_PAGE_COUNT 3 +char hotbarSlotPages[] = //{ + //"#o?^BG{}" + //"P()+|S&=" + //"EFH....." +//}; +"#oS8BG{}" +"P(?MTWX)" +"|&=EFH.."; + +extern bool isFileSystemEnabled; +void EmptyFunctionForInfoboxes(bool t) {} + +bool hasShowedFatUnusableDlg = false; +void Game::Update() { + ClearScreen(RGBA16(1, 27, 31, 1)); + if (dialogShown) { + // TODO + dialogPosition -= dialogPosition / 2; // todo: make it independent of fps + if (dialogPosition <= 1) { + dialogPosition = 0; + } else { + //glPolyFmt(POLY_ALPHA(3)); + //FillRectangle(BLACK, 0, 0, 256, 192); + //glPolyFmt(POLY_ALPHA(31)); + } + } else { + // go back down + if (dialogPosition == 0) dialogPosition = 1; + dialogPosition *= 2; + if (dialogPosition > 192) + dialogPosition = 192; + } + if (dialogShown) goto drawDialogAndReturn; // pause the game + + // + { + float fElapsedTime = 0.0166667f; + if (gameMode != Mode_Maker) UpdateGameLogic(fElapsedTime); + Draw(); + + switch (gameMode) { + case Mode_Maker: { + Point pTouch = { touch.px, touch.py }; + bool canTouchLevel = true; + if (hasInventoryOpen) { + Rectangle r = { 220, 5, 32, 16 }; + u16 color = 0xffff; + bool click = false; + click = RectangleContains(r, pTouch); + if (click) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + } + DrawImageColored(&lrArrowImage[1], r.width, r.height, r.x, r.y, 0, color); + if (hasClickedPreviouslyMaker[0] && !click) { + hasInventoryOpen = false; + } + hasClickedPreviouslyMaker[0] = click; + + for (int i = 0; i < 9; i++) { + Rectangle r = { 2 + i * 24, 1, 24, 28 }; + u16 color = 0xffff; + click = RectangleContains(r, pTouch); + if (click) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + } + // draw inventory slot shit + char c; + if (i < 8) c = hotbarSlots[i]; else c = '>'; + if (inventoryHotbarSelectedIdx == i) { + DrawImageColored(&itemSImage[0], r.width, r.height, r.x, r.y, 0, color); + } else { + DrawImageColored(&itemImage[0], r.width, r.height, r.x, r.y, 0, color); + } + // draw the tile itself slightly lower and to the right + DrawTile(c, r.x + 4, r.y + 4); + if (hasClickedPreviouslyMaker[i+1] && !click) { + if (i < 8) inventoryHotbarSelectedIdx = i; else { + hotbarSlotPage++; + if (hotbarSlotPage >= HOTBAR_SLOT_PAGE_COUNT) { + hotbarSlotPage = 0; + } + memcpy(hotbarSlots, 8 * hotbarSlotPage + hotbarSlotPages, 8); + } + } + hasClickedPreviouslyMaker[i+1] = click; + } + } else { + Rectangle r = { 0, 5, 32, 16 }; + u16 color = 0xffff; + bool click = false; + click = RectangleContains(r, pTouch); + if (click) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + } + DrawImageColored(&lrArrowImage[0], r.width, r.height, r.x, r.y, 0, color); + if (hasClickedPreviouslyMaker[0] && !click) { + hasInventoryOpen = true; + } + hasClickedPreviouslyMaker[0] = click; + } + if (hasRightMenuOpen) { + Rectangle r = { 200, 25, 32, 16 }; + u16 color = 0xffff; + bool click = false; + click = RectangleContains(r, pTouch); + if (click) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + } + DrawImageColored(&lrArrowImage[0], r.width, r.height, r.x, r.y, 0, color); + if (hasClickedPreviouslyMaker[10] && !click) { + hasRightMenuOpen = false; + } + hasClickedPreviouslyMaker[10] = click; + + r = { 256 - 34, 23, 34, 70 }; + FillRectangle(RGBA16(0x1A, 0x1A, 0x1B, 1), r.x, r.y, r.width, r.height); + if (RectangleContains(r, pTouch)) { + canTouchLevel = false; + } + r = { 226, 26, 28, 30 }; + color = 0xffff; + click = false; + if (RectangleContains(r, pTouch)) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + click = true; + } + DrawImageColored(&resetImage[0], r.width, r.height, r.x, r.y, 0, color); + if (!click && hasClickedPreviouslyMaker[11]) { + //LogMsg("Tried to reset"); + ShowDialog(ResetLevel, "Yes", "No", "Do you really want to", "reset this level? You will", "lose all the progress you've made."); + } + hasClickedPreviouslyMaker[11] = click; + r = { 226, 60, 28, 30 }; + color = 0xffff; + click = false; + if (RectangleContains(r, pTouch)) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + click = true; + } + DrawImageColored(&eraseImage[0], r.width, r.height, r.x, r.y, 0, color); + if (!click && hasClickedPreviouslyMaker[12]) { + // too bad we wont add dialog yet + isInEraseMode ^= 1; + } + hasClickedPreviouslyMaker[12] = click; + } else { + Rectangle r = { 230, 25, 32, 16 }; + u16 color = 0xffff; + bool click = false; + click = RectangleContains(r, pTouch); + if (click) { + color &= 0xBDEF; // 127,127,127 + canTouchLevel = false; + } + DrawImageColored(&lrArrowImage[1], r.width, r.height, r.x, r.y, 0, color); + if (hasClickedPreviouslyMaker[10] && !click) { + hasRightMenuOpen = true; + } + hasClickedPreviouslyMaker[10] = click; + } + if (isInEraseMode) isInCopyMode = false; + /**/ if (isInEraseMode) DrawImage(&ermodImage[0], 64, 16, 0, hasInventoryOpen ? 25 : 0); + else if (isInCopyMode) DrawImage(&cpmodImage[0], 64, 16, 0, hasInventoryOpen ? 25 : 0); + if (GetKeyDownState(KEY_START)) { + gameMode = Mode_Game; + DoLevelInitStuff(); + } + if (GetKeyDownState(KEY_SELECT)) { + gameMode = Mode_Game; + memcpy(sLevelBeforePlay, sLevel, nLevelHeight * nLevelWidth); + } + + int nTileWidth = 16; + int nTileHeight = 16; + int nVisibleTilesX = SCREEN_WIDTH / nTileWidth; + int nVisibleTilesY = SCREEN_HEIGHT/nTileHeight; + if (canTouchLevel) { + float fOffsetX = fCameraPosX - (float)nVisibleTilesX / 2.0f; + float fOffsetY = fCameraPosY - (float)nVisibleTilesY / 2.0f; + + if(fOffsetX <= 0.0f) fOffsetX = 0.0f; + if(fOffsetY <= 0.0f) fOffsetY = 0.0f; + if(fOffsetX > (float)(nLevelWidth - nVisibleTilesX)) fOffsetX = nLevelWidth - nVisibleTilesX; + if(fOffsetY > (float)(nLevelHeight- nVisibleTilesY)) fOffsetY = nLevelHeight- nVisibleTilesY; + + int worldPosX = pTouch.x + fOffsetX * 16; + int worldPosY = pTouch.y + fOffsetY * 16; + int tilePosX = worldPosX / 16; + int tilePosY = worldPosY / 16; + + if (pTouch.x != 0 && pTouch.y != 0) { // has touched screen + if (isInEraseMode) { + SetTile('.', tilePosX, tilePosY); + isDraggingStuff = false; + } else if (multigrabMode) { + if (isDrawing) { + draggedRectX2 = tilePosX; + draggedRectY2 = tilePosY; + } else { + if (draggedRectX1 != -1) { + isDraggingStuff = true; + worldDragPosX = draggedRectX1 * 16; + worldDragPosY = draggedRectY1 * 16; + } else { + isDrawing = true; + draggedRectX1 = tilePosX; + draggedRectY1 = tilePosY; + } + } + } else { + if (isDraggingStuff) { + worldDragPosX += worldPosX - lastWorldTouchPosX; + worldDragPosY += worldPosY - lastWorldTouchPosY; + } else { + char c = hotbarSlots[inventoryHotbarSelectedIdx]; + if (c != '.') { + if (GetTile(tilePosX, tilePosY) == '.' || isDrawing) { + SetTile(c, tilePosX, tilePosY); + isDrawing = true; + } else { + // drag + isDraggingStuff = true; + draggedRectX1 = tilePosX; + draggedRectX2 = tilePosX; + draggedRectY1 = tilePosY; + draggedRectY2 = tilePosY; + + worldDragPosX = tilePosX * 16; + worldDragPosY = tilePosY * 16; + } + } + } + } + } else { + isDrawing = false; + if (isDraggingStuff) { + isDraggingStuff = false; + /* + // release? + bool goRightToLeft = worldDragPosX > draggedRectX1; + bool goDownToUp = worldDragPosY > draggedRectY1; + + + if (goDownToUp) { + if (goRightToLeft) { + for (int i = draggedRectX2; i >= draggedRectX1; i--) { + for (int j = draggedRectY2; j >= draggedRectY1; j--) { + int offsetX = (int)roundf(worldDragPosX / 16.f) + i - draggedRectX1; + int offsetY = (int)roundf(worldDragPosY / 16.f) + j - draggedRectY1; + char c = GetTile(i, j); + SetTile('.', i, j); + SetTile(c, offsetX, offsetY); + } + } + } else { + for (int i = draggedRectX2; i >= draggedRectX1; i--) { + for (int j = draggedRectY1; j <= draggedRectY1; j++) { + int offsetX = (int)roundf(worldDragPosX / 16.f) + i - draggedRectX1; + int offsetY = (int)roundf(worldDragPosY / 16.f) + j - draggedRectY1; + char c = GetTile(i, j); + SetTile('.', i, j); + SetTile(c, offsetX, offsetY); + } + } + } + } else { + if (goRightToLeft) { + for (int i = draggedRectX1; i <= draggedRectX2; i++) { + for (int j = draggedRectY2; j >= draggedRectY1; j--) { + int offsetX = (int)roundf(worldDragPosX / 16.f) + i - draggedRectX1; + int offsetY = (int)roundf(worldDragPosY / 16.f) + j - draggedRectY1; + char c = GetTile(i, j); + SetTile('.', i, j); + SetTile(c, offsetX, offsetY); + } + } + } else { + for (int i = draggedRectX1; i <= draggedRectX2; i++) { + for (int j = draggedRectY1; j <= draggedRectY1; j++) { + int offsetX = (int)roundf(worldDragPosX / 16.f) + i - draggedRectX1; + int offsetY = (int)roundf(worldDragPosY / 16.f) + j - draggedRectY1; + char c = GetTile(i, j); + SetTile('.', i, j); + SetTile(c, offsetX, offsetY); + } + } + } + }*/ + int i = draggedRectX1; + int j = draggedRectY1; + int offsetX = (int)roundf(worldDragPosX / 16.f) + i - draggedRectX1; + int offsetY = (int)roundf(worldDragPosY / 16.f) + j - draggedRectY1; + char c = GetTile(i, j); + char cDest = GetTile(offsetX, offsetY); + if (!isInCopyMode) SetTile('.', i, j); + switch (cDest) { + // here we do special actions, for example, placing + // a mushroom on top of a ? block + case '?': + if (c == 'M') c = '^'; // mushroom + if (c == 'T') c = 'A'; // extra clock + if (c == 'W') c = 'Q'; // flower + if (c == 'X') c = 'L'; // life up + break; // todo + } + SetTile(c, offsetX, offsetY); + + draggedRectX1 = -1; + draggedRectX2 = -1; + draggedRectY1 = -1; + draggedRectY2 = -1; + + worldDragPosX = 0; + worldDragPosY = 0; + } + } + lastWorldTouchPosX = worldPosX; + lastWorldTouchPosY = worldPosY; + } + + fCameraPosY = nVisibleTilesY / 2.f; + float moveSpeed = 10; + bool b = GetKeyState(KEY_Y); + if (b) moveSpeed *= 2; + bool hitDirKey = false; + if (GetKeyState(KEY_UP)) { + fPlayerPosY -= moveSpeed * fElapsedTime; + if (fPlayerPosY < 0) fPlayerPosY = 0; + hitDirKey = true; + } + if (GetKeyState(KEY_DOWN)) { + fPlayerPosY += moveSpeed * fElapsedTime; + if (fPlayerPosY >= nLevelHeight) fPlayerPosY = nLevelHeight - 1; + } + if (GetKeyState(KEY_LEFT)) { + fPlayerPosX -= moveSpeed * fElapsedTime; + if (fPlayerPosX < 0) fPlayerPosX = 0; + while (fPlayerPosX < fCameraPosX - 6) { + fCameraPosX -= moveSpeed * fElapsedTime; + } + hitDirKey = true; + } + if (GetKeyState(KEY_RIGHT)) { + fPlayerPosX += moveSpeed * fElapsedTime; + if (fPlayerPosX >= nLevelWidth - 1) fPlayerPosX = nLevelWidth - 1; + while (fPlayerPosX > fCameraPosX + 6) { + fCameraPosX += moveSpeed * fElapsedTime; + } + hitDirKey = true; + } + if (GetKeyDownState(KEY_L)) { + isInEraseMode ^= 1; + isInCopyMode = 0; + } + if (GetKeyDownState(KEY_R)) { + isInCopyMode ^= 1; + isInEraseMode = 0; + } + if (GetKeyDownState(KEY_Y) && !hitDirKey) { + // call player + fPlayerPosX = fCameraPosX; + fPlayerPosY = fCameraPosY; + } + + if (playerState == State_Dead && fPlayerPosY > nLevelHeight) { + fPlayerPosX = fCameraPosX; + fPlayerPosY = fCameraPosY; + } + playerState = State_Idle; + + break; // todo + } + case Mode_Title: { + //DrawString((SCREEN_WIDTH - 20 * 6) / 2, 40, WHITE, "GAME MAKER PROTOTYPE", 0); + DrawImage(logoImage, 256, 32, (SCREEN_WIDTH - 192) / 2, 40); + if (hasPressedLROrStart) { + DrawString((SCREEN_WIDTH - 26 * 6) / 2, 100, WHITE, "Touch the buttons to play!", 0); + Rectangle r[2] = { { (SCREEN_WIDTH - 96) / 2, 110, 48, 36}, {(SCREEN_WIDTH - 96) / 2 + 48, 110, 48, 36}}; + Point pTouch = { touch.px, touch.py }; + bool clicked[2] = { RectangleContains(r[0], pTouch), RectangleContains(r[1], pTouch)}; + const char* texts[2] = { makeText, playText }; + for (int i = 0; i < 2; i++) { + DrawImage(&cbordImage[!clicked[i]], 48, 36, r[i].x, r[i].y); + DrawString(r[i].x + 25 - strlen(texts[i]) * 3, r[i].y + 21, BLACK, texts[i], 0); + DrawString(r[i].x + 24 - strlen(texts[i]) * 3, r[i].y + 20, WHITE, texts[i], 0); + } + if (!clicked[0] && hasClickedPreviously[0]) { + hasPressedLROrStart = false; + //gameMode = Mode_Maker; + SetToMakerMode(); + LoadLevelToMem(level_1, level_1_width, level_1_height); + canEditLevel = true; + } + if (!clicked[1] && hasClickedPreviously[1]) { + hasPressedLROrStart = false; + gameMode = Mode_Game; + } + memcpy(hasClickedPreviously, clicked, sizeof(clicked)); + } else { + DrawString((SCREEN_WIDTH - 13 * 6) / 2, 140, WHITE, "Press [L]/[R]", 0); + if (GetKeyState(KEY_L) && GetKeyState(KEY_R)) { + hasPressedLROrStart = true; + } + } + case Mode_Game: { + // draw game UI? + char ch[100]; + memset(ch, 0, 100); + sprintf(ch, "%09d \xb%03d", score, (int)inGameTime); + DrawString(SCREEN_WIDTH - 6 - 6 * strlen(ch), 5, WHITE, ch, 0); + memset(ch, 0, 100); + sprintf(ch, "\x9x%02d", gems); + DrawString(6, 5, WHITE, ch, 0); + + int hpBarWidth = 184, hpBarX = 36; + if (lastHP == 0) lastHP = hp; + else lastHP = (lastHP * 7.f + (float)hp) / 8.f; + int curHPWidth = (int)((float)lastHP * (float)hpBarWidth / (float)maxHP); + FillRectangle(RED & 0xBDEF, hpBarX, 15, hpBarWidth, 3); + FillRectangle(RED, hpBarX, 15, curHPWidth, 3); + + memset(ch, 0, 100); + sprintf(ch, "%d", 0); + DrawString(hpBarX - 3 - 6 * strlen(ch), 13, WHITE, ch, 0); + memset(ch, 0, 100); + sprintf(ch, "%d", maxHP); + DrawString(hpBarX + hpBarWidth + 3, 13, WHITE, ch, 0); + + break; // todo + } + } + } + if (doSetToMakerMode) { + doSetToMakerMode = false; + gameMode = Mode_Maker; + ResetEverything(); + } + } +drawDialogAndReturn: + if (dialogPosition < 191) DrawDialog(dialogShown); + + if (!hasShowedFatUnusableDlg && !isFileSystemEnabled) { + hasShowedFatUnusableDlg = true; + //ShowDialog(EmptyFunctionForInfoboxes, "OK", "OK", "The file system could not", "be initialized, you can't save", "levels."); + } + +} +void LoadLevelToMem(char* c, int w, int h) { + if (sLevel) delete[] sLevel; + if (sLevelBeforePlay) delete[] sLevelBeforePlay; + nLevelWidth = w; + nLevelHeight = h; + sLevel = new char[nLevelWidth * nLevelHeight]; + sLevelBeforePlay = new char[nLevelWidth * nLevelHeight]; + memcpy(sLevel, c, nLevelHeight * nLevelWidth); + memcpy(sLevelBeforePlay, c, nLevelHeight * nLevelWidth); +} +void DoLevelInitStuff() { + memcpy(sLevelBeforePlay, sLevel, nLevelHeight * nLevelWidth); + playerState = State_Idle; + int count = nLevelWidth * nLevelHeight; + fPlayerPosX = fPlayerPosY = fPlayerVelX = fPlayerVelY = 0; + for (int i = 0; i < count; i++) { + /* + if (sLevel[i] == '&') { + if (sLevel[i + nLevelWidth] == 'G') + sLevel[i + nLevelWidth] = '}'; + else + sLevel[i + nLevelWidth] = '{'; + } + */ + + if (sLevel[i] == 'S') { + fPlayerPosX = i % nLevelWidth; + fPlayerPosY = i / nLevelWidth; + //sLevel[i] = '{'; + } + } + gems = 0; + score = 0; + inGameTime = maxTime; + hp = 1; + maxHP = 1; + inGameTime = 500; + gems = 0; + score = 0; + stunTimer = 0; + lastHP = 1; + ending = false; + endingStage = 0; +} +void Game::Init() { + LoadLevelToMem(level_1_old, level_1_width, level_1_height); + DoLevelInitStuff(); +} +void Game::LoadContent() { + LogMsg("Loading content"); + decompress(tilesBitmap, textureCacheBmp, LZ77); + tileSpriteID = glLoadTileSet(tilesImage, 16, 16, 128, 128, GL_RGBA, TEXTURE_SIZE_128, TEXTURE_SIZE_128, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 256, NULL, (u8*)textureCacheBmp); + decompress(characterBitmap, textureCacheBmp, LZ77); + plyrSpriteID = glLoadTileSet(playrImage, 16, 16, 128, 16, GL_RGBA, TEXTURE_SIZE_128, TEXTURE_SIZE_16, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 256, NULL, (u8*)textureCacheBmp); + decompress(clapperboardBitmap, textureCacheBmp, LZ77); + cbrdSpriteID = glLoadTileSet(cbordImage, 48, 36, 128, 64, GL_RGBA, TEXTURE_SIZE_128, TEXTURE_SIZE_64, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(itemselBitmap, textureCacheBmp, LZ77); + itemSelSpriteID = glLoadTileSet(itemSImage, 32,32,32,32, GL_RGBA, TEXTURE_SIZE_32, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(itemBitmap, textureCacheBmp, LZ77); + itemSpriteID = glLoadTileSet(itemImage, 32,32,32,32, GL_RGBA, TEXTURE_SIZE_32, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(lr_arrowsBitmap, textureCacheBmp, LZ77); + lrArSpriteID = glLoadTileSet(lrArrowImage, 32,16,32,32, GL_RGBA, TEXTURE_SIZE_32, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(undoBitmap, textureCacheBmp, LZ77); + undoSpriteID = glLoadTileSet(undoImage, 32,32,32,32, GL_RGBA, TEXTURE_SIZE_32, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(eraseBitmap, textureCacheBmp, LZ77); + eraseSpriteID = glLoadTileSet(eraseImage, 32,32,32,32, GL_RGBA, TEXTURE_SIZE_32, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(resetBitmap, textureCacheBmp, LZ77); + resetSpriteID = glLoadTileSet(resetImage, 32,32,32,32, GL_RGBA, TEXTURE_SIZE_32, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(erase_modeBitmap, textureCacheBmp, LZ77); + ermodSpriteID = glLoadTileSet(ermodImage,64,16,64,16, GL_RGBA, TEXTURE_SIZE_64, TEXTURE_SIZE_16, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(copy_modeBitmap, textureCacheBmp, LZ77); + cpmodSpriteID = glLoadTileSet(cpmodImage,64,16,64,16, GL_RGBA, TEXTURE_SIZE_64, TEXTURE_SIZE_16, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(dialog_bgBitmap, textureCacheBmp, LZ77); + dlgBgSpriteID = glLoadTileSet(dlgBgImage,256,256,256,256, GL_RGBA, TEXTURE_SIZE_256, TEXTURE_SIZE_256, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(dialogbtnBitmap, textureCacheBmp, LZ77); + dlgBtnSpriteID = glLoadTileSet(dlgBtnImage,128,32,128,32, GL_RGBA, TEXTURE_SIZE_128, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + decompress(logoBitmap, textureCacheBmp, LZ77); + logoSpriteID = glLoadTileSet(logoImage,256,32,256,32, GL_RGBA, TEXTURE_SIZE_256, TEXTURE_SIZE_32, GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T|TEXGEN_OFF|GL_TEXTURE_COLOR0_TRANSPARENT, 0, NULL, (u8*)textureCacheBmp); + + memcpy(hotbarSlots, hotbarSlotPages, 8); + + Enemy::CommonLoad(); +} +time_t currentTime; +void Title::Update(){ + DrawString((SCREEN_WIDTH - 20 * 6) / 2, 30, WHITE, "GAME MAKER PROTOTYPE", 0); + DrawString((SCREEN_WIDTH - 30 * 6) / 2, 90, WHITE, "Touch the Touch Screen to play", 0); + if ((touch.px != 0 || touch.py != 0) && !(prevTouch.px != 0 || prevTouch.py != 0)) { + LogMsg("Touch2 at x:%d, y:%d", touch.px, touch.py); + //mode = PlayMode::Mode::Game; + } + char s[100]; + memset(s,0,100); + currentTime = time(nullptr); + auto m = gmtime(¤tTime); + strftime(s, 99, "TOD: %a, %d %b %Y at %H:%M:%S", m); + DrawString(3, 3, WHITE, s, 0); +} +void Title::Init() { + +} +void Title::LoadContent() { + +} \ No newline at end of file diff --git a/source/TestGame.hpp b/source/TestGame.hpp new file mode 100644 index 0000000..4b8e80e --- /dev/null +++ b/source/TestGame.hpp @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + Programmed by iProgramInCpp + + TestGame module +---------------------------------------------------------------------------------*/ +#include "EngineDec.h" +#include "Utils.hpp" + +#ifndef TESTGAME_HPP +#define TESTGAME_HPP + +//extern short tiles[128*128]; +//extern short character[128*16]; +//extern short clapperboard[128*64]; +extern glImage tilesImage[64]; +extern int BlockBumpedX, BlockBumpedY; +extern float fPlayerPosX, fPlayerPosY; +extern float maxTime; +extern int gems, score; +extern float inGameTime; +extern int nLevelWidth, nLevelHeight; +namespace Game { + void UpdateGameLogic(float fElapsedTime); + void Update(); + void Draw(); + void Init(); + void LoadContent(); +}; +namespace Title { + void Update(); + void Init(); + void LoadContent(); +}; +void DrawTile(char sTileID, int x, int y, char sTileIDAbove = '.', bool renderInInventory = true, int tileX = 0, int tileY = 0); +#define DIR_UP 0x01 +#define DIR_DOWN 0x02 +#define DIR_LEFT 0x04 +#define DIR_RIGHT 0x08 +bool IsSolid(char c, int directions); +char GetTile(int x, int y); +void SetTile(char c, int x, int y); +void IncreaseMaxHP(); +void DamagePlayer(); +void HealPlayer(); +typedef void DialogResultFunction(bool); // the bool represents saidYes +void ShowDialog(DialogResultFunction* f, const char* dialogYes, const char* dialogNo, const char* dlgRow1, const char* dlgRow2 = nullptr, const char* dlgRow3 = nullptr); +#endif//TESTGAME_HPP \ No newline at end of file diff --git a/source/Typeface.h b/source/Typeface.h new file mode 100644 index 0000000..1eb4775 --- /dev/null +++ b/source/Typeface.h @@ -0,0 +1,259 @@ +const char MainFont[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0x1F, 0x0F, 0x3E, 0xCC, 0x08, //0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x7E, 0x99, 0xA5, 0xA5, 0x7E, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0x55, 0x00, 0x55, 0x00, 0x55, + 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0xFF, 0x55, 0xFF, 0x55, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/source/Utils.cpp b/source/Utils.cpp new file mode 100644 index 0000000..4cfe62e --- /dev/null +++ b/source/Utils.cpp @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + Programmed by iProgramInCpp + + Utils module +---------------------------------------------------------------------------------*/ +#include "Utils.hpp" + +void LogMsg(const char* s, ...) { + + char c[10240]; + va_list v; + va_start(v, s); + memset(c,0,sizeof(c)); + vsprintf(c, s, v); + va_end(v); + puts(c); + +} \ No newline at end of file diff --git a/source/Utils.hpp b/source/Utils.hpp new file mode 100644 index 0000000..7310a03 --- /dev/null +++ b/source/Utils.hpp @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------- + GAME PROJECT + [ July 29, 2020 ] + Programmed by iProgramInCpp + + Utils module +---------------------------------------------------------------------------------*/ +#include +#include +#include +void LogMsg(const char* m, ...); \ No newline at end of file