Added game files

This commit is contained in:
DavidSM64 2015-10-19 17:27:01 -05:00
parent 704637d45e
commit 340b9b6900
31 changed files with 5427 additions and 0 deletions

207
Makefile Normal file
View file

@ -0,0 +1,207 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# 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
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := Minicraft3DS
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
APP_TITLE := Test
APP_DESCRIPTION := ???
APP_AUTHOR := Davideesk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lsfil -lpng -ljpeg -lz -lsf2d -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB) $(PORTLIBS)
#---------------------------------------------------------------------------------
# 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 TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(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)/*.*)))
#---------------------------------------------------------------------------------
# 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)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(TARGET)-strip.elf $(TARGET).cia $(TARGET).3ds
#---------------------------------------------------------------------------------
$(TARGET)-strip.elf: $(BUILD)
@$(STRIP) $(TARGET).elf -o $(TARGET)-strip.elf
#---------------------------------------------------------------------------------
cci: $(TARGET)-strip.elf
@makerom -f cci -rsf resources/$(TARGET).rsf -target d -exefslogo -elf $(TARGET)-strip.elf -o $(TARGET).3ds
@echo "built ... sfil_sample.3ds"
#---------------------------------------------------------------------------------
cia: $(TARGET)-strip.elf
@makerom -f cia -o $(TARGET).cia -elf $(TARGET)-strip.elf -rsf resources/$(TARGET).rsf -exefslogo -target t
@echo "built ... sfil_sample.cia"
#---------------------------------------------------------------------------------
send: $(BUILD)
@3dslink $(TARGET).3dsx
#---------------------------------------------------------------------------------
run: $(BUILD)
@citra $(TARGET).3dsx
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.jpeg.o: %.jpeg
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.png.o : %.png
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

BIN
data/Font.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
data/icons2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
resources/bossdeath.raw Normal file

Binary file not shown.

BIN
resources/craft.raw Normal file

Binary file not shown.

BIN
resources/death.raw Normal file

Binary file not shown.

BIN
resources/monsterhurt.raw Normal file

Binary file not shown.

BIN
resources/pickup.raw Normal file

Binary file not shown.

BIN
resources/playerhurt.raw Normal file

Binary file not shown.

BIN
resources/test.raw Normal file

Binary file not shown.

136
source/Crafting.c Normal file
View file

@ -0,0 +1,136 @@
#include "Crafting.h"
void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv){
int i, j;
for(i = 0; i < rm->size; i++){
rm->recipes[i].canCraft = true;
for(j = 0; j < rm->recipes[i].numOfCosts; j++){
if(countItemInv(rm->recipes[i].costs[j].costItem,0,inv) < rm->recipes[i].costs[j].costAmount){
rm->recipes[i].canCraft = false;
}
}
}
}
int compareCanCraft(const void * ra, const void * rb) {
Recipe* r1 = (Recipe*)ra;
Recipe* r2 = (Recipe*)rb;
if (r1->canCraft && !r2->canCraft) return -1;
if (!r1->canCraft && r2->canCraft) return 1;
return r1->order - r2->order; // Needed for stable sorting.
}
void sortRecipes(RecipeManager * rm){
qsort(rm->recipes,rm->size,sizeof(Recipe),compareCanCraft);
}
void deductCost(Cost c, Inventory * inv){
Item* item = getItemFromInventory(c.costItem, inv);
if(!item->onlyOne){
item->countLevel -= c.costAmount;
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, inv);
} else {
removeItemFromInventory(item->slotNum, inv);
}
}
bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv){
if(r->canCraft){
int i;
for(i=0;i<r->numOfCosts;++i) deductCost(r->costs[i], inv);
Item item = newItem(r->itemResult,r->itemAmountLevel);
if(!item.onlyOne && countItemInv(item.id,item.countLevel,inv) > 0){
getItemFromInventory(item.id, inv)->countLevel += r->itemAmountLevel;
} else{
pushItemToInventoryFront(item, inv);
}
checkCanCraftRecipes(rm, inv);
sortRecipes(rm);
return true;
}
return false;
}
Cost newCost(int i, int c){
Cost nc;
nc.costItem = i;
nc.costAmount = c;
return nc;
}
u8 curPlace = 0;
Recipe defineRecipe(int item, int amountOrLevel, int numArgs, ...){
Recipe r;
r.itemResult = item;
r.itemAmountLevel = amountOrLevel;
r.numOfCosts = numArgs;
int i;
va_list al;
numArgs <<= 1; // Did this to get rid of a warning.
va_start(al,numArgs);
for(i=0;i<r.numOfCosts;++i) r.costs[i] = newCost(va_arg(al,int), va_arg(al,int));
va_end(al);
r.order = curPlace;
curPlace++;
return r;
}
void initRecipes(){
curPlace = 0;
workbenchRecipes.size = 16;
workbenchRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (workbenchRecipes.size));
workbenchRecipes.recipes[0] = defineRecipe(ITEM_WORKBENCH,1,1,ITEM_WOOD,20);
workbenchRecipes.recipes[1] = defineRecipe(ITEM_FURNACE,1,1,ITEM_STONE,20);
workbenchRecipes.recipes[2] = defineRecipe(ITEM_OVEN,1,1,ITEM_STONE,20);
workbenchRecipes.recipes[3] = defineRecipe(ITEM_CHEST,1,1,ITEM_WOOD,20);
workbenchRecipes.recipes[4] = defineRecipe(ITEM_ANVIL,1,1,ITEM_IRONINGOT,5);
workbenchRecipes.recipes[5] = defineRecipe(ITEM_LANTERN,1,3,ITEM_WOOD,5,ITEM_SLIME,10,ITEM_GLASS,4);
workbenchRecipes.recipes[6] = defineRecipe(TOOL_SWORD,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[7] = defineRecipe(TOOL_AXE,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[8] = defineRecipe(TOOL_HOE,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[9] = defineRecipe(TOOL_PICKAXE,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[10] = defineRecipe(TOOL_SHOVEL,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[11] = defineRecipe(TOOL_SWORD,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[12] = defineRecipe(TOOL_AXE,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[13] = defineRecipe(TOOL_HOE,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[14] = defineRecipe(TOOL_PICKAXE,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[15] = defineRecipe(TOOL_SHOVEL,1,2,ITEM_WOOD,5,ITEM_STONE,5);
anvilRecipes.size = 15;
anvilRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (anvilRecipes.size));
anvilRecipes.recipes[0] = defineRecipe(TOOL_SWORD,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[1] = defineRecipe(TOOL_AXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[2] = defineRecipe(TOOL_HOE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[3] = defineRecipe(TOOL_PICKAXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[4] = defineRecipe(TOOL_SHOVEL,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[5] = defineRecipe(TOOL_SWORD,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[6] = defineRecipe(TOOL_AXE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[7] = defineRecipe(TOOL_HOE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[8] = defineRecipe(TOOL_PICKAXE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[9] = defineRecipe(TOOL_SHOVEL,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[10] = defineRecipe(TOOL_SWORD,4,2,ITEM_WOOD,5,ITEM_GEM,50);
anvilRecipes.recipes[11] = defineRecipe(TOOL_AXE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
anvilRecipes.recipes[12] = defineRecipe(TOOL_HOE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
anvilRecipes.recipes[13] = defineRecipe(TOOL_PICKAXE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
anvilRecipes.recipes[14] = defineRecipe(TOOL_SHOVEL,4,2,ITEM_WOOD,5,ITEM_GEM,50);
furnaceRecipes.size = 3;
furnaceRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (furnaceRecipes.size));
furnaceRecipes.recipes[0] = defineRecipe(ITEM_IRONINGOT,1,2,ITEM_IRONORE,4,ITEM_COAL,1);
furnaceRecipes.recipes[1] = defineRecipe(ITEM_GOLDINGOT,1,2,ITEM_GOLDORE,4,ITEM_COAL,1);
furnaceRecipes.recipes[2] = defineRecipe(ITEM_GLASS,1,2,ITEM_SAND,4,ITEM_COAL,1);
ovenRecipes.size = 1;
ovenRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (ovenRecipes.size));
ovenRecipes.recipes[0] = defineRecipe(ITEM_BREAD,1,1,ITEM_WHEAT,4);
}
/* Free up allocated memory */
void freeRecipes(){
free(workbenchRecipes.recipes);
free(ovenRecipes.recipes);
free(furnaceRecipes.recipes);
free(anvilRecipes.recipes);
}

35
source/Crafting.h Normal file
View file

@ -0,0 +1,35 @@
#pragma once
#include <stdarg.h>
#include "Item.h"
typedef struct {
int costItem;
int costAmount;
} Cost;
typedef struct {
bool canCraft;
int itemResult;
int itemAmountLevel;
s8 numOfCosts;
Cost costs[6]; // Up to 6 items for costs
u8 order; // Used for stable sorting.
} Recipe;
typedef struct {
int size;
Recipe * recipes;
} RecipeManager;
RecipeManager workbenchRecipes;
RecipeManager furnaceRecipes;
RecipeManager ovenRecipes;
RecipeManager anvilRecipes;
void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv);
void sortRecipes(RecipeManager * rm);
bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv);
void initRecipes();
void freeRecipes();

204
source/Entity.c Normal file
View file

@ -0,0 +1,204 @@
#include "Entity.h"
#define PI 3.141592654
double gaussrand()
{
static double U, V;
static int phase = 0;
double Z;
if(phase == 0) {
U = (rand() + 1.) / (RAND_MAX + 2.);
V = rand() / (RAND_MAX + 1.);
Z = sqrt(-2 * log(U)) * sin(2 * PI * V);
} else
Z = sqrt(-2 * log(U)) * cos(2 * PI * V);
phase = 1 - phase;
return Z;
}
Entity newItemEntity(Item item, int x, int y, int level){
Entity e;
e.type = ENTITY_ITEM;
e.level = level;
e.entityItem.age = 0;
e.entityItem.item = item;
e.x = x;
e.y = y;
e.xr = 3;
e.yr = 3;
e.canPass = false;
e.entityItem.xx = x;
e.entityItem.yy = y;
e.entityItem.zz = 2;
e.entityItem.xa = gaussrand() * 0.1;
e.entityItem.ya = gaussrand() * 0.1;
e.entityItem.za = ((float)rand() / RAND_MAX) * 0.45 + 1;
return e;
}
void assignInventory(Entity* e){
if(eManager.nextInv > 300) return;
e->entityFurniture.inv = &eManager.invs[eManager.nextInv];
eManager.nextInv++;
}
Entity newFurnitureEntity(int itemID,Inventory * invPtr, int x, int y, int level){
Entity e;
e.type = ENTITY_FURNITURE;
e.level = level;
e.x = x;
e.y = y;
e.xr = 3;
e.yr = 3;
e.entityFurniture.itemID = itemID;
e.canPass = false;
if(itemID == ITEM_LANTERN) e.entityFurniture.r = 8;
else if(itemID == ITEM_CHEST){
if(invPtr == NULL)assignInventory(&e);
else e.entityFurniture.inv = invPtr;
}
return e;
}
Entity newZombieEntity(int lvl, int x, int y, int level){
Entity e;
e.type = ENTITY_ZOMBIE;
e.level = level;
e.x = x;
e.y = y;
e.hurtTime = 0;
e.xKnockback = 0;
e.yKnockback = 0;
e.zombie.lvl = lvl;
e.zombie.health = lvl * lvl * 10;
e.zombie.dir = 0;
e.xr = 4;
e.yr = 3;
e.canPass = false;
switch(lvl){
case 2: e.zombie.color = 0xCC8282FF; break;
case 3: e.zombie.color = 0xEFEFEFFF; break;
case 4: e.zombie.color = 0x6262AAFF; break;
default: e.zombie.color = 0x95DB95FF; break;
}
return e;
}
Entity newSlimeEntity(int lvl, int x, int y, int level){
Entity e;
e.type = ENTITY_SLIME;
e.level = level;
e.x = x;
e.y = y;
e.hurtTime = 0;
e.xKnockback = 0;
e.yKnockback = 0;
e.slime.lvl = lvl;
e.slime.xa = 0;
e.slime.ya = 0;
e.slime.dir = 0;
e.slime.health = lvl * lvl * 5;
e.xr = 4;
e.yr = 3;
e.canPass = false;
switch(lvl){
case 2: e.slime.color = 0xCC8282FF; break;
case 3: e.slime.color = 0xEFEFEFFF; break;
case 4: e.slime.color = 0x6262AAFF; break;
default: e.slime.color = 0x95DB95FF; break;
}
return e;
}
Entity newAirWizardEntity(int x, int y, int level){
Entity e;
e.type = ENTITY_AIRWIZARD;
e.level = level;
e.x = x;
e.y = y;
e.hurtTime = 0;
e.xKnockback = 0;
e.yKnockback = 0;
e.wizard.dir = 0;
e.wizard.health = 2000;
e.wizard.attackDelay = 0;
e.wizard.attackTime = 0;
e.wizard.attackType = 0;
e.wizard.xa = 0;
e.wizard.ya = 0;
e.xr = 4;
e.yr = 3;
e.canPass = true;
return e;
}
Entity newSparkEntity(Entity* parent, float xa, float ya){
Entity e;
e.type = ENTITY_SPARK;
e.spark.age = 0;
e.spark.parent = parent;
e.spark.xa = xa;
e.spark.ya = ya;
e.spark.xx = parent->x;
e.spark.yy = parent->y;
e.xr = 3;
e.yr = 3;
e.canPass = true;
return e;
}
Entity newTextParticleEntity(char * str, u32 color, int x, int y, int level){
Entity e;
e.type = ENTITY_TEXTPARTICLE;
e.level = level;
e.textParticle.color = color;
e.textParticle.age = 0;
e.textParticle.text = (char*)calloc(strlen(str),sizeof(char));
strncpy(e.textParticle.text,str,strlen(str));
e.x = x;
e.y = y;
e.canPass = true;
e.textParticle.xx = x;
e.textParticle.yy = y;
e.textParticle.zz = 2;
e.textParticle.xa = gaussrand() * 0.3;
e.textParticle.ya = gaussrand() * 0.2;
e.textParticle.za = ((float)rand() / RAND_MAX) * 0.7 + 2;
return e;
}
Entity newSmashParticleEntity(int x, int y, int level){
Entity e;
e.type = ENTITY_SMASHPARTICLE;
e.level = level;
e.smashParticle.age = 0;
e.x = x;
e.y = y;
e.canPass = true;
playSound(snd_monsterHurt);
return e;
}
void addEntityToList(Entity e, EntityManager* em){
e.slotNum = em->lastSlot[e.level];
em->entities[e.level][em->lastSlot[e.level]] = e;
++em->lastSlot[e.level];
}
Entity nullEntity;
void removeEntityFromList(Entity * e,int level,EntityManager* em){
int i;
if(em->entities[level][e->slotNum].type == ENTITY_TEXTPARTICLE) free(em->entities[level][e->slotNum].textParticle.text);
for(i = e->slotNum; i < em->lastSlot[level];++i){
em->entities[level][i] = em->entities[level][i + 1]; // Move the items down.
em->entities[level][i].slotNum = i;
}
em->lastSlot[level]--;
em->entities[level][em->lastSlot[level]] = nullEntity; // Make the last slot null.
}

170
source/Entity.h Normal file
View file

@ -0,0 +1,170 @@
#pragma once
#include "Crafting.h"
#include <stdlib.h>
// Entity types
#define ENTITY_NULL 0
#define ENTITY_ITEM 1
#define ENTITY_FURNITURE 2
#define ENTITY_ZOMBIE 3
#define ENTITY_SLIME 4
#define ENTITY_AIRWIZARD 5
#define ENTITY_SPARK 6
#define ENTITY_TEXTPARTICLE 7
#define ENTITY_SMASHPARTICLE 8
#define ENTITY_PLAYER 9
typedef struct Entity Entity;
typedef struct {
s8 ax;
s8 ay;
u8 dir;
s8 health;
s8 stamina;
s8 staminaRecharge;
s8 staminaRechargeDelay;
s8 attackTimer;
u8 spawnTrigger;
bool isDead;
bool hasWon;
bool hasWonSaved;
s8 endTimer;
s16 walkDist;
bool isCarrying;
bool isSwimming;
int swimTimer;
int score;
Inventory* inv;
Item* activeItem;
} Player;
typedef struct {
float xa;
float ya;
float za;
float xx;
float yy;
float zz;
s16 age;
Item item;
} EntityItem;
typedef struct {
s16 itemID;
bool active;
s8 r; // light radius for lantern. window select for chests.
Inventory* inv; // Points to chest inventory.
s16 oSel; // other selection inside the chest inv.
} EntityFurniture;
typedef struct {
s8 xa;
s8 ya;
s16 health;
s8 dir;
s8 lvl;
s8 randWalkTime;
s8 walkDist;
u32 color;
} Zombie;
typedef struct {
s8 xa;
s8 ya;
s16 health;
s8 lvl;
s8 dir;
s8 jumpTime;
u32 color;
} Slime;
typedef struct {
s8 xa;
s8 ya;
s16 health;
s8 randWalkTime;
s8 walkDist;
s8 dir;
int attackDelay;
int attackTime;
int attackType;
s8 spriteAdjust;
} AirWizard;
typedef struct {
Entity* parent;
s16 age;
float xa;
float ya;
float xx;
float yy;
} Spark;
typedef struct {
float xa;
float ya;
float za;
float xx;
float yy;
float zz;
s16 age;
char* text;
int color;
} TextParticleEntity;
typedef struct {
s16 age;
} SmashParticleEntity;
struct Entity {
s16 x;
s16 y;
s8 xKnockback,yKnockback;
u8 xr,yr;
u8 type;
u8 level;
s8 hurtTime;
s16 slotNum; // Read-only. Do not mess with this.
bool canPass;
bool canSwim;
union {
Player p;
EntityItem entityItem;
EntityFurniture entityFurniture;
Zombie zombie;
Slime slime;
AirWizard wizard;
Spark spark;
TextParticleEntity textParticle;
SmashParticleEntity smashParticle;
};
};
typedef struct {
Entity entities[5][1000];
Entity wizardSparks[120];
s16 lastSlot[5];
Inventory invs[301];//1 for the player, 300 for chests.
s16 nextInv;
} EntityManager;
EntityManager eManager;
s8 currentLevel;
double gaussrand();
Entity newItemEntity(Item item, int x, int y, int level);
Entity newFurnitureEntity(int itemID,Inventory * invPtr, int x, int y, int level);
Entity newZombieEntity(int lvl, int x, int y, int level);
Entity newSlimeEntity(int lvl, int x, int y, int level);
Entity newAirWizardEntity(int x, int y, int level);
Entity newSparkEntity(Entity* parent, float xa, float ya);
Entity newTextParticleEntity(char * str, u32 color, int xa, int ya, int level);
Entity newSmashParticleEntity(int xa, int ya, int level);
void addEntityToList(Entity e, EntityManager* em);
void removeEntityFromList(Entity * e,int level,EntityManager* em);

1319
source/Globals.c Normal file

File diff suppressed because it is too large Load diff

100
source/Globals.h Normal file
View file

@ -0,0 +1,100 @@
#pragma once
#include <3ds.h>
#include "SaveLoad.h"
#include "Input.h"
#define CIRCLEPAD 0xF0000000
#define CSTICK 0x0F000000
#define MENU_NONE 0
#define MENU_TITLE 1
#define MENU_TUTORIAL 2
#define MENU_ABOUT 3
#define MENU_SETTINGS 4
#define MENU_INVENTORY 5
#define MENU_CRAFTING 6
#define MENU_CONTAINER 7
#define MENU_WIN 8
#define MENU_LOSE 9
#define MENU_PAUSED 10
#define MENU_LOADGAME 11
#define TILE_NULL 255
#define TILE_GRASS 0
#define TILE_TREE 1
#define TILE_ROCK 2
#define TILE_DIRT 3
#define TILE_SAND 4
#define TILE_WATER 5
#define TILE_LAVA 6
#define TILE_CACTUS 7
#define TILE_FLOWER 8
#define TILE_IRONORE 9
#define TILE_GOLDORE 10
#define TILE_GEMORE 11
#define TILE_FARM 12
#define TILE_WHEAT 13
#define TILE_SAPLING_TREE 14
#define TILE_SAPLING_CACTUS 15
#define TILE_STAIRS_DOWN 16
#define TILE_STAIRS_UP 17
#define TILE_CLOUD 18
#define TILE_HARDROCK 19
#define TILE_CLOUDCACTUS 20
#define TILE_HOLE 21
bool screenShot;
extern char versionText[34];
Entity player;
sf2d_texture * lightScreen;
sf2d_texture * minimap[5];
u8 map[5][128*128];
u8 data[5][128*128];
u8 treeTable[256];
u16 rockTable[256];
u16 grassTable[16];
char currentFileName[256];
extern u8 currentMenu;
extern char fpsstr[];
u8 initGame;
Item noItem;
int airWizardHealthDisplay;
u32 tickCount;
RecipeManager* currentRecipes;
Entity* curChestEntity;
s16 curInvSel;
bool quitGame;
s8 currentSelection;
void tickTile(int x, int y);
bool tileIsSolid(int tile, Entity * e);
s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir);
void tickEntity(Entity* e);
void trySpawn(int count, int level);
int getTile(int x, int y);
u32 getTileColor(int tile);
void setTile(int id, int x, int y);
int getData(int x, int y);
void setData(int id, int x, int y);
bool intersectsEntity(int x, int y, int r, Entity* e);
bool EntityBlocksEntity(Entity* e1, Entity* e2);
void EntityVsEntity(Entity* e1, Entity* e2);
void entityTileInteract(Entity* e, int tile,int x, int y);
void initPlayer();
void tickPlayer();
void playerAttack();
bool isSwimming();
bool playerUseEnergy(int amount);
void playerHurtTile(int tile, int xt, int yt, int damage, int dir);
bool playerIntersectsEntity(Entity* e);
void playerEntityInteract(Entity* e);

20
source/Input.c Normal file
View file

@ -0,0 +1,20 @@
#include "Input.h"
void toggleKey(Key* key, bool held, bool down){
key->down = held;
key->clicked = down;
}
void tickKeys(u32 held, u32 down){
toggleKey(&k_up, held & k_up.input, down & k_up.input);
toggleKey(&k_down, held & k_down.input, down & k_down.input);
toggleKey(&k_left, held & k_left.input, down & k_left.input);
toggleKey(&k_right, held & k_right.input, down & k_right.input);
toggleKey(&k_pause, held & k_pause.input, down & k_pause.input);
toggleKey(&k_attack, held & k_attack.input, down & k_attack.input);
toggleKey(&k_menu, held & k_menu.input, down & k_menu.input);
toggleKey(&k_accept, held & k_accept.input, down & k_accept.input);
toggleKey(&k_decline, held & k_decline.input, down & k_decline.input);
toggleKey(&k_delete, held & k_delete.input, down & k_delete.input);
}

21
source/Input.h Normal file
View file

@ -0,0 +1,21 @@
#include <3ds.h>
typedef struct {
bool down, clicked;
int input;
} Key;
Key k_null;
Key k_up;
Key k_down;
Key k_left;
Key k_right;
Key k_attack;
Key k_menu;
Key k_pause;
Key k_accept;
Key k_decline;
Key k_delete;
void tickKeys(u32 held,u32 down);
bool clicked(Key key);

238
source/Item.c Normal file
View file

@ -0,0 +1,238 @@
#include "Item.h"
char currentName[16];
bool isItemEmpty(Item* item){
if(item->id < 6 || item->onlyOne == true) return false;
if(item->countLevel < 1) return true;
return false;
}
void pushItemToInventoryFront(Item item, Inventory * inv){
if(inv->lastSlot < 300) ++inv->lastSlot;
int i;
for(i = inv->lastSlot;i > 0;--i){
inv->items[i] = inv->items[i-1]; // Move the items up the list.
inv->items[i].slotNum = i;
}
item.invPtr = (int*)inv;
inv->items[0] = item;
inv->items[0].slotNum = 0;
}
void addItemToInventory(Item item, Inventory * inv){
if(!item.onlyOne){
int i;
for(i = 0;i < inv->lastSlot;++i){ //Search inventory if item already exists.
if(inv->items[i].id == item.id){
inv->items[i].countLevel+=item.countLevel;
return;
}
}
}
item.slotNum = inv->lastSlot;
item.invPtr = (int*)inv;
inv->items[inv->lastSlot] = item;
++inv->lastSlot;
}
void removeItemFromCurrentInv(Item* item){
removeItemFromInventory(item->slotNum, (Inventory*)item->invPtr);
}
Item nullItem;
void removeItemFromInventory(int slot, Inventory * inv){
int i;
for(i = slot;i < inv->lastSlot - 1;++i){
inv->items[i] = inv->items[i + 1]; // Move the items down.
inv->items[i].slotNum--;
}
--inv->lastSlot;
inv->items[inv->lastSlot] = nullItem; // Make the last slot null.
}
Item newItem(int id, int cLevel){
Item item;
item.id = id;
if(id != ITEM_NULL){
if(cLevel > 999) cLevel = 999;
item.countLevel = cLevel;
if(id < 7 || id > 27) item.onlyOne = true; // Tools + Furniture.
else item.onlyOne = false;
}
item.chestPtr = NULL;
return item;
}
Item* getItemFromInventory(int itemID, Inventory * inv){
int i;
for(i = 0;i < inv->lastSlot;++i){
if(inv->items[i].id == itemID){
return &inv->items[i];
}
}
return (Item*)NULL;
}
int countItemInv(int itemID, int level, Inventory* inv){
int i, count = 0;
for(i = 0;i < inv->lastSlot;++i){
if(inv->items[i].id == itemID){
if(inv->items[i].onlyOne){
if(level == inv->items[i].countLevel) count++;
} else count += inv->items[i].countLevel;
}
}
return count;
}
char* getItemName(int itemID, int countLevel){
switch(itemID){
case TOOL_SHOVEL:
switch(countLevel){
case 1: return "Rock Shovel";
case 2: return "Iron Shovel";
case 3: return "Gold Shovel";
case 4: return "Gem Shovel";
default: return "Wood Shovel";
}
case TOOL_HOE:
switch(countLevel){
case 1: return "Rock Hoe";
case 2: return "Iron Hoe";
case 3: return "Gold Hoe";
case 4: return "Gem Hoe";
default: return "Wood Hoe";
}
case TOOL_SWORD:
switch(countLevel){
case 1: return "Rock Sword";
case 2: return "Iron Sword";
case 3: return "Gold Sword";
case 4: return "Gem Sword";
default: return "Wood Sword";
}
case TOOL_PICKAXE:
switch(countLevel){
case 1: return "Rock Pickaxe";
case 2: return "Iron Pickaxe";
case 3: return "Gold Pickaxe";
case 4: return "Gem Pickaxe";
default: return "Wood Pickaxe";
}
case TOOL_AXE:
switch(countLevel){
case 1: return "Rock Axe";
case 2: return "Iron Axe";
case 3: return "Gold Axe";
case 4: return "Gem Axe";
default: return "Wood Axe";
}
case ITEM_ANVIL: return "Anvil";
case ITEM_CHEST: return "Chest";
case ITEM_OVEN: return "Oven";
case ITEM_FURNACE: return "Furnace";
case ITEM_WORKBENCH: return "Workbench";
case ITEM_LANTERN: return "Lantern";
case ITEM_POWGLOVE: return "Power Glove";
case ITEM_FLOWER: sprintf(currentName,"%d Flower", countLevel); return currentName;
case ITEM_WOOD: sprintf(currentName,"%d Wood", countLevel); return currentName;
case ITEM_STONE: sprintf(currentName,"%d Stone", countLevel); return currentName;
case ITEM_SAND: sprintf(currentName,"%d Sand", countLevel); return currentName;
case ITEM_DIRT: sprintf(currentName,"%d Dirt", countLevel); return currentName;
case ITEM_CLOUD: sprintf(currentName,"%d Cloud", countLevel); return currentName;
case ITEM_ACORN: sprintf(currentName,"%d Acorn", countLevel); return currentName;
case ITEM_CACTUS: sprintf(currentName,"%d Cactus", countLevel); return currentName;
case ITEM_SEEDS: sprintf(currentName,"%d Seeds", countLevel); return currentName;
case ITEM_WHEAT: sprintf(currentName,"%d Wheat", countLevel); return currentName;
case ITEM_FLESH: sprintf(currentName,"%d Flesh", countLevel); return currentName;
case ITEM_BREAD: sprintf(currentName,"%d Bread", countLevel); return currentName;
case ITEM_APPLE: sprintf(currentName,"%d Apple", countLevel); return currentName;
case ITEM_COAL: sprintf(currentName,"%d Coal", countLevel); return currentName;
case ITEM_IRONORE: sprintf(currentName,"%d Iron ore", countLevel); return currentName;
case ITEM_GOLDORE: sprintf(currentName,"%d Gold ore", countLevel); return currentName;
case ITEM_IRONINGOT: sprintf(currentName,"%d Iron ingot", countLevel); return currentName;
case ITEM_GOLDINGOT: sprintf(currentName,"%d Gold ingot", countLevel); return currentName;
case ITEM_GLASS: sprintf(currentName,"%d Glass", countLevel); return currentName;
case ITEM_GEM: sprintf(currentName,"%d Gem", countLevel); return currentName;
case ITEM_SLIME: sprintf(currentName,"%d Slime", countLevel); return currentName;
default: return ""; // null
}
}
char* getBasicItemName(int itemID, int countLevel){
switch(itemID){
case TOOL_SHOVEL:
switch(countLevel){
case 1: return "Rock Shovel";
case 2: return "Iron Shovel";
case 3: return "Gold Shovel";
case 4: return "Gem Shovel";
default: return "Wood Shovel";
}
case TOOL_HOE:
switch(countLevel){
case 1: return "Rock Hoe";
case 2: return "Iron Hoe";
case 3: return "Gold Hoe";
case 4: return "Gem Hoe";
default: return "Wood Hoe";
}
case TOOL_SWORD:
switch(countLevel){
case 1: return "Rock Sword";
case 2: return "Iron Sword";
case 3: return "Gold Sword";
case 4: return "Gem Sword";
default: return "Wood Sword";
}
case TOOL_PICKAXE:
switch(countLevel){
case 1: return "Rock Pickaxe";
case 2: return "Iron Pickaxe";
case 3: return "Gold Pickaxe";
case 4: return "Gem Pickaxe";
default: return "Wood Pickaxe";
}
case TOOL_AXE:
switch(countLevel){
case 1: return "Rock Axe";
case 2: return "Iron Axe";
case 3: return "Gold Axe";
case 4: return "Gem Axe";
default: return "Wood Axe";
}
case ITEM_ANVIL: return "Anvil";
case ITEM_CHEST: return "Chest";
case ITEM_OVEN: return "Oven";
case ITEM_FURNACE: return "Furnace";
case ITEM_WORKBENCH: return "Workbench";
case ITEM_LANTERN: return "Lantern";
case ITEM_POWGLOVE: return "Power Glove";
case ITEM_FLOWER: return "Flower";
case ITEM_WOOD: return "Wood";
case ITEM_STONE: return "Stone";
case ITEM_SAND: return "Sand";
case ITEM_DIRT: return "Dirt";
case ITEM_CLOUD: return "Cloud";
case ITEM_ACORN: return "Acorn";
case ITEM_CACTUS: return "Cactus";
case ITEM_SEEDS: return "Seeds";
case ITEM_WHEAT: return "Wheat";
case ITEM_FLESH: return "Flesh";
case ITEM_BREAD: return "Bread";
case ITEM_APPLE: return "Apple";
case ITEM_COAL: return "Coal";
case ITEM_IRONORE: return "Iron ore";
case ITEM_GOLDORE: return "Gold ore";
case ITEM_IRONINGOT: return "Iron ingot";
case ITEM_GOLDINGOT: return "Gold ingot";
case ITEM_GLASS: return "Glass";
case ITEM_GEM: return "Gem";
case ITEM_SLIME: return "Slime";
default: return ""; // null
}
}

70
source/Item.h Normal file
View file

@ -0,0 +1,70 @@
#pragma once
#include <3ds.h>
#include <sf2d.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "Sound.h"
#define ITEM_NULL 0
#define TOOL_SHOVEL 1
#define TOOL_HOE 2
#define TOOL_SWORD 3
#define TOOL_PICKAXE 4
#define TOOL_AXE 5
#define ITEM_POWGLOVE 6
#define ITEM_FLOWER 7
#define ITEM_WOOD 8
#define ITEM_STONE 9
#define ITEM_SAND 10
#define ITEM_DIRT 11
#define ITEM_CLOUD 12
#define ITEM_ACORN 13
#define ITEM_CACTUS 14
#define ITEM_SEEDS 15
#define ITEM_WHEAT 16
#define ITEM_FLESH 17
#define ITEM_BREAD 18
#define ITEM_APPLE 19
#define ITEM_SLIME 20
#define ITEM_COAL 21
#define ITEM_IRONORE 22
#define ITEM_GOLDORE 23
#define ITEM_IRONINGOT 24
#define ITEM_GOLDINGOT 25
#define ITEM_GLASS 26
#define ITEM_GEM 27
#define ITEM_ANVIL 28
#define ITEM_CHEST 29
#define ITEM_OVEN 30
#define ITEM_FURNACE 31
#define ITEM_WORKBENCH 32
#define ITEM_LANTERN 33
typedef struct Inventory Inventory;
typedef struct {
s16 id;
s16 countLevel; // Count for items, Level for tools.
s16 slotNum; // Read-only. Do not mess with this.
bool onlyOne;
int* invPtr; // pointer to current inventory.
Inventory * chestPtr; // pointer to chest inventory for chest item.
} Item;
struct Inventory {
Item items[300]; // Maximum of 300 slots in every inventory.
s16 lastSlot; // lastSlot can also be used to read the size of the inventory.
};
bool isItemEmpty(Item* item);
Item newItem(int id, int cLevel);
char* getItemName(int itemID, int countLevel);
char* getBasicItemName(int itemID, int countLevel);
void pushItemToInventoryFront(Item item, Inventory * inv);
void addItemToInventory(Item item, Inventory * inv);
void removeItemFromCurrentInv(Item* item);
void removeItemFromInventory(int slot, Inventory * inv);
Item* getItemFromInventory(int itemID, Inventory * inv);
int countItemInv(int itemID,int level, Inventory* inv);

403
source/MapGen.c Normal file
View file

@ -0,0 +1,403 @@
#include "MapGen.h"
int w = 0;
int h = 0;
float nextFloat(){
return (float)rand()/RAND_MAX;
}
double sample(double * values, int x, int y) {
return values[(x & (w - 1)) + (y & (h - 1)) * w];
}
double * Noise(int width, int height, int featureSize) {
w = width;
h = height;
double * values = malloc(sizeof(double) * w * h);
int x, y;
for(x = 0; x < w; x+=featureSize){
for(y = 0; y < w; y+=featureSize){
values[(x & (w - 1)) + (y & (h - 1)) * w] = nextFloat() * 2 - 1;
}
}
int stepSize = featureSize;
double scale = 1.0 / w;
double scaleMod = 1;
do {
int halfStep = stepSize / 2;
for(x = 0; x < w; x+=stepSize){
for(y = 0; y < w; y+=stepSize){
double a = sample(values,x, y);
double b = sample(values,x + stepSize, y);
double c = sample(values,x, y + stepSize);
double d = sample(values,x + stepSize, y + stepSize);
double e = (a + b + c + d) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale;
values[((x + halfStep) & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = e;
}
}
for(x = 0; x < w; x+=stepSize){
for(y = 0; y < w; y+=stepSize){
double a = sample(values,x, y);
double b = sample(values,x + stepSize, y);
double c = sample(values,x, y + stepSize);
double d = sample(values,x + halfStep, y + halfStep);
double e = sample(values,x + halfStep, y - halfStep);
double f = sample(values,x - halfStep, y + halfStep);
double H = (a + b + d + e) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5;
double g = (a + c + d + f) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5;
values[((x + halfStep) & (w - 1)) + (y & (h - 1)) * w] = H;
values[(x & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = g;
}
}
stepSize /= 2;
scale *= (scaleMod + 0.8);
scaleMod *= 0.3;
} while (stepSize > 1);
return values;
}
void newSeed(){
srand(time(NULL));
}
void createAndValidateTopMap(int w, int h, u8 * map, u8 * data) {
do {
createTopMap(w, h, map, data);
int count[256]={[0 ... 255] = 0};
int i;
for (i = 0; i < w * h; ++i) count[map[i] & 0xff]++;
if (count[TILE_ROCK & 0xff] < 100) continue;
if (count[TILE_SAND & 0xff] < 100) continue;
if (count[TILE_GRASS & 0xff] < 100) continue;
if (count[TILE_TREE & 0xff] < 100) continue;
if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue;
return;
} while (true);
}
void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
do {
createUndergroundMap(w, h, depthLevel, map, data);
int count[256]={[0 ... 255] = 0};
int i = 0;
for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++;
if (count[TILE_ROCK & 0xff] < 100) continue;
if (count[TILE_DIRT & 0xff] < 100) continue;
switch(depthLevel){
case 1: if (count[TILE_IRONORE & 0xff] < 20) continue; break;
case 2: if (count[TILE_GOLDORE & 0xff] < 20) continue; break;
case 3: if (count[TILE_GEMORE & 0xff] < 20) continue; break;
}
if (depthLevel < 3) if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue;
return;
} while (true);
}
void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data) {
do {
createSkyMap(w, h, map, data);
int count[256]={[0 ... 255] = 0};
int i = 0;
for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++;
if (count[TILE_CLOUD & 0xff] < 1600) continue;
if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue;
return;
} while (true);
}
void createTopMap(int w, int h, u8 * map, u8 * data) {
double* mnoise1 = Noise(w, h, 16);
double* mnoise2 = Noise(w, h, 16);
double* mnoise3 = Noise(w, h, 16);
double* noise1 = Noise(w, h, 32);
double* noise2 = Noise(w, h, 32);
int x,y,i,j,k,xx,yy;
for(x = 0; x < w; ++x){
for(y = 0; y < w; ++y){
int i = x + y * w;
double val = fabs(noise1[i] - noise2[i]) * 3 - 2;
double mval = fabs(mnoise1[i] - mnoise2[i]);
mval = fabs(mval - mnoise3[i]) * 3 - 2;
double xd = x / (w - 1.0) * 2 - 1;
double yd = y / (h - 1.0) * 2 - 1;
if (xd < 0) xd = -xd;
if (yd < 0) yd = -yd;
double dist = xd >= yd ? xd : yd;
dist = dist * dist * dist * dist;
dist = dist * dist * dist * dist;
val = val + 1 - dist * 20; //-2 before to -21.0 after
if (val < -0.5) {
map[i] = TILE_WATER;
} else if (val > 0.5 && mval < -1) {
map[i] = TILE_ROCK;
} else {
map[i] = TILE_GRASS;
}
}
}
for (i = 0; i < w * h / 2800; ++i) {
int xs = rand()%w;
int ys = rand()%h;
for (k = 0; k < 10; ++k) {
x = xs + (rand()%21) - 10;
y = ys + (rand()%21) - 10;
for (j = 0; j < 100; ++j) {
int xo = x + (rand()%5) - (rand()%5);
int yo = y + (rand()%5) - (rand()%5);
for (yy = yo - 1;yy <= yo + 1; ++yy){
for(xx = xo - 1; xx <= xo + 1; ++xx){
if (xx >= 0 && yy >= 0 && xx < w && yy < h) if (map[xx + yy * w] == TILE_GRASS) map[xx + yy * w] = TILE_SAND;
}
}
}
}
}
for (i = 0; i < w * h / 400; ++i) {
x = rand()%w;
y = rand()%h;
for (j = 0; j < 200; ++j) {
xx = x + (rand()%15) - (rand()%15);
yy = y + (rand()%15) - (rand()%15);
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_GRASS) {
map[xx + yy * w] = TILE_TREE;
}
}
}
}
for (i = 0; i < w * h / 800; ++i) {
x = rand()%w;
y = rand()%h;
for (j = 0; j < 30;++j) {
xx = x + (rand()%5) - (rand()%5);
yy = y + (rand()%5) - (rand()%5);
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_GRASS) {
map[xx + yy * w] = TILE_FLOWER;
data[xx + yy * w] = rand()%4; // determines mirroring.
}
}
}
}
for (i = 0; i < w * h / 100; ++i) {
xx = rand()%w;
yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_SAND) {
map[xx + yy * w] = TILE_CACTUS;
}
}
}
int sCount, attempts = 0;
for (sCount = 0; sCount < 4;) {
xx = rand()%w;
yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_ROCK)
{
map[xx + yy * w] = TILE_STAIRS_DOWN;
map[xx + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + yy * w] = TILE_ROCK;
map[xx + (yy-1) * w] = TILE_ROCK;
map[(xx-1) + yy * w] = TILE_ROCK;
map[(xx-1) + (yy-1) * w] = TILE_ROCK;
map[(xx+1) + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + (yy-1) * w] = TILE_ROCK;
map[(xx-1) + (yy+1) * w] = TILE_ROCK;
++sCount;
}
}
if(attempts < (w*h/100)) ++attempts; else break;
}
free(mnoise1);
free(mnoise2);
free(mnoise3);
free(noise1);
free(noise2);
return;
}
void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
double* mnoise1 = Noise(w, h, 16);
double* mnoise2 = Noise(w, h, 16);
double* mnoise3 = Noise(w, h, 16);
double* nnoise1 = Noise(w, h, 16);
double* nnoise2 = Noise(w, h, 16);
double* nnoise3 = Noise(w, h, 16);
double* wnoise1 = Noise(w, h, 16);
double* wnoise2 = Noise(w, h, 16);
double* wnoise3 = Noise(w, h, 16);
double* noise1 = Noise(w, h, 32);
double* noise2 = Noise(w, h, 32);
int x, y;
for(x = 0; x < w; ++x){
for(y = 0; y < w; ++y){
int i = x + y * w;
double val = fabs(noise1[i] - noise2[i]) * 3 - 2;
double mval = fabs(mnoise1[i] - mnoise2[i]);
mval = fabs(mval - mnoise3[i]) * 3 - 2;
double nval = fabs(nnoise1[i] - nnoise2[i]);
nval = fabs(nval - nnoise3[i]) * 3 - 2;
double wval = fabs(wnoise1[i] - wnoise2[i]);
wval = fabs(nval - wnoise3[i]) * 3 - 2;
double xd = x / (w - 1.0) * 2 - 1;
double yd = y / (h - 1.0) * 2 - 1;
if (xd < 0) xd = -xd;
if (yd < 0) yd = -yd;
double dist = xd >= yd ? xd : yd;
dist = dist * dist * dist * dist;
dist = dist * dist * dist * dist;
val = val + 1 - dist * 20;
if (val > -2 && wval < -2.0 + (depthLevel) / 2 * 3) {
if (depthLevel > 2)
map[i] = TILE_LAVA;
else
map[i] = TILE_WATER;
} else if (val > -2 && (mval < -1.7 || nval < -1.4)) {
map[i] = TILE_DIRT;
} else {
map[i] = TILE_ROCK;
}
}
}
int i,j;
for (i = 0; i < w * h / 400; ++i) {
int x = rand()%w;
int y = rand()%h;
for(j = 0; j < 30; ++j) {
int xx = x + (rand()%5) - (rand()%5);
int yy = y + (rand()%5) - (rand()%5);
if (xx >= 2 && yy >= 2 && xx < w-2 && yy < h-2) {
if (map[xx + yy * w] == TILE_ROCK) {
map[xx + yy * w] = TILE_IRONORE+depthLevel-1;
}
}
}
}
if (depthLevel < 3){
int sCount, attempts = 0;
for (sCount = 0; sCount < 4;) {
int xx = rand()%w;
int yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_ROCK){
map[xx + yy * w] = TILE_STAIRS_DOWN;
map[xx + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + yy * w] = TILE_ROCK;
map[xx + (yy-1) * w] = TILE_ROCK;
map[(xx-1) + yy * w] = TILE_ROCK;
map[(xx-1) + (yy-1) * w] = TILE_ROCK;
map[(xx+1) + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + (yy-1) * w] = TILE_ROCK;
map[(xx-1) + (yy+1) * w] = TILE_ROCK;
++sCount;
}
}
if(attempts < (w*h/100)) ++attempts; else break;
}
}
free(mnoise1);
free(mnoise2);
free(mnoise3);
free(nnoise1);
free(nnoise2);
free(nnoise3);
free(wnoise1);
free(wnoise2);
free(wnoise3);
free(noise1);
free(noise2);
}
void createSkyMap(int w, int h, u8 * map, u8 * data) {
double* noise1 = Noise(w, h, 8);
double* noise2 = Noise(w, h, 8);
int x, y;
for(x = 0; x < w; ++x){
for(y = 0; y < w; ++y){
int i = x + y * w;
double val = fabs(noise1[i] - noise2[i]) * 3 - 2;
double xd = x / (w - 1.0) * 2 - 1;
double yd = y / (h - 1.0) * 2 - 1;
if (xd < 0) xd = -xd;
if (yd < 0) yd = -yd;
double dist = xd >= yd ? xd : yd;
dist = dist * dist * dist * dist;
dist = dist * dist * dist * dist;
val = -val * 1 - 2.2;
val = val + 1 - dist * 20;
if (val < -0.25) {
map[i] = -1; // render nothing
} else {
map[i] = TILE_CLOUD;
}
}
}
int i;
for (i = 0; i < w * h / 50; ++i) {
int xx = rand()%w;
int yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_CLOUD) map[xx + yy * w] = TILE_CLOUDCACTUS;
}
}
int sCount, attempts = 0;
for (sCount = 0; sCount < 2;) {
int xx = rand()%w;
int yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_CLOUD)
{
map[xx + yy * w] = TILE_STAIRS_DOWN;
map[xx + (yy+1) * w] = TILE_CLOUD;
map[(xx+1) + yy * w] = TILE_CLOUD;
map[xx + (yy-1) * w] = TILE_CLOUD;
map[(xx-1) + yy * w] = TILE_CLOUD;
map[(xx-1) + (yy-1) * w] = TILE_CLOUD;
map[(xx+1) + (yy+1) * w] = TILE_CLOUD;
map[(xx+1) + (yy-1) * w] = TILE_CLOUD;
map[(xx-1) + (yy+1) * w] = TILE_CLOUD;
++sCount;
}
}
if(attempts < w*h) ++attempts; else break;
}
free(noise1);
free(noise2);
}

19
source/MapGen.h Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <3ds.h>
#include "Globals.h"
float nextFloat();
double sample(double * values, int x, int y);
double * Noise(int w, int h, int featureSize);
void newSeed();
void createAndValidateTopMap(int w, int h, u8 * map, u8 * data);
void createTopMap(int w, int h, u8 * map, u8 * data);
void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data);
void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data);
void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data);
void createSkyMap(int w, int h, u8 * map, u8 * data);

1006
source/Menu.c Normal file

File diff suppressed because it is too large Load diff

12
source/Menu.h Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include <3ds.h>
#include <string.h>
#include <sf2d.h>
#include <dirent.h>
#include <ctype.h>
#include "Render.h"
void renderMenu(int menu,int xscr,int yscr);
void tickMenu(int menu);

826
source/Render.c Normal file
View file

@ -0,0 +1,826 @@
#include "Render.h"
void render(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=8;}
if((bits & 2) > 0){scaleY=-2;yp+=8;}
sf2d_draw_texture_part_scale(icons,xp<<1,yp<<1,xTile,yTile,8,8,scaleX,scaleY);
}
void renderb(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=8;}
if((bits & 2) > 0){scaleY=-2;yp+=8;}
sf2d_draw_texture_part_scale_blend(icons,xp<<1,yp<<1,xTile,yTile,8,8,scaleX,scaleY,color);
}
void renderr(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float rotate){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=8;}
if((bits & 2) > 0){scaleY=-2;yp+=8;}
sf2d_draw_texture_part_rotate_scale(icons,xp<<1,yp<<1,rotate,xTile,yTile,8,8,scaleX,scaleY);
}
void renderc(s32 xp, s32 yp, u32 xTile, u32 yTile,int sizeX, int sizeY, u8 bits){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=sizeX;}
if((bits & 2) > 0){scaleY=-2;yp+=sizeY;}
sf2d_draw_texture_part_scale(icons,xp<<1,yp<<1,xTile,yTile,sizeX,sizeY,scaleX,scaleY);
}
void renderbc(s32 xp, s32 yp, u32 xTile, u32 yTile,int sizeX, int sizeY, u8 bits, u32 color){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=sizeX;}
if((bits & 2) > 0){scaleY=-2;yp+=sizeY;}
sf2d_draw_texture_part_scale_blend(icons,xp<<1,yp<<1,xTile,yTile,sizeX,sizeY,scaleX,scaleY,color);
}
void render16(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=16;}
if((bits & 2) > 0){scaleY=-2;yp+=16;}
sf2d_draw_texture_part_scale(icons,xp<<1,yp<<1,xTile,yTile,16,16,scaleX,scaleY);
}
void render16c(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits,float scaleX, float scaleY){
xp-=offsetX;
yp-=offsetY;
if((bits & 1) > 0){scaleX=-scaleX;xp+=16;}
if((bits & 2) > 0){scaleY=-scaleY;yp+=16;}
sf2d_draw_texture_part_scale(icons,xp*scaleX,yp*scaleY,xTile,yTile,16,16,scaleX,scaleY);
}
void render16b(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits,u32 color){
xp-=offsetX;
yp-=offsetY;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=16;}
if((bits & 2) > 0){scaleY=-2;yp+=16;}
sf2d_draw_texture_part_scale_blend(icons,xp<<1,yp<<1,xTile,yTile,16,16,scaleX,scaleY,color);
}
void render16s(s32 xp, s32 yp, u32 tile, u8 bits,u32 color){
xp-=offsetX;
yp-=offsetY;
int xTile = tile & 255;
int yTile = tile >> 8;
int scaleX = 2, scaleY = 2;
if((bits & 1) > 0){scaleX=-2;xp+=16;}
if((bits & 2) > 0){scaleY=-2;yp+=16;}
sf2d_draw_texture_part_scale_blend(icons,xp<<1,yp<<1,xTile,yTile,16,16,scaleX,scaleY,color);
}
void renderTitle(int x, int y){
sf2d_draw_texture_part_scale(icons,(x-26)<<1,y<<1,0,240,104,16,2.0,2.0); // MINICRAFT
sf2d_draw_texture_part(icons,x+48,y+52,104,240,152,16); // 3DS HOMEBREW EDITION
}
void renderButtonIcon(u32 keyIcon, int x, int y, float scale){
switch(keyIcon){
case CIRCLEPAD: render16c(x,y,96,208,0,scale,scale); break;
case KEY_CPAD_UP: render16c(x,y,112,208,0,scale,scale); break;
case KEY_CPAD_LEFT: render16c(x,y,128,208,0,scale,scale); break;
case KEY_CPAD_DOWN: render16c(x,y,144,208,0,scale,scale); break;
case KEY_CPAD_RIGHT: render16c(x,y,160,208,0,scale,scale); break;
/* New 3DS only */
case CSTICK: render16c(x,y,176,208,0,scale,scale); break;
case KEY_CSTICK_UP: render16c(x,y,192,208,0,scale,scale); break;
case KEY_CSTICK_LEFT: render16c(x,y,208,208,0,scale,scale); break;
case KEY_CSTICK_DOWN: render16c(x,y,224,208,0,scale,scale); break;
case KEY_CSTICK_RIGHT: render16c(x,y,240,208,0,scale,scale); break;
case KEY_A: render16c(x,y,0,224,0,scale,scale); break;
case KEY_B: render16c(x,y,16,224,0,scale,scale); break;
case KEY_X: render16c(x,y,32,224,0,scale,scale); break;
case KEY_Y: render16c(x,y,48,224,0,scale,scale); break;
case KEY_DUP: render16c(x,y,64,224,0,scale,scale); break;
case KEY_DLEFT: render16c(x,y,80,224,0,scale,scale); break;
case KEY_DDOWN: render16c(x,y,96,224,0,scale,scale); break;
case KEY_DRIGHT: render16c(x,y,112,224,0,scale,scale); break;
case KEY_START:
render16c(x-8,y,128,224,0,scale,scale);
render16c(x+8,y,144,224,0,scale,scale);
break;
case KEY_SELECT:
render16c(x-8,y,160,224,0,scale,scale);
render16c(x+8,y,176,224,0,scale,scale);
break;
case KEY_L: render16c(x,y,192,224,0,scale,scale); break;
case KEY_R: render16c(x,y,208,224,0,scale,scale); break;
/* New 3DS only */
case KEY_ZL: render16c(x,y,224,224,0,scale,scale); break;
case KEY_ZR: render16c(x,y,240,224,0,scale,scale); break;
}
}
int getFrame(int a, int b, int s){
return (a == s) ? 0 : ((a < b-1) ? 8 : 16);
}
void renderFrame(int x1, int y1, int x2, int y2, u32 bgColor){
int startX = x1;
int startY = y1;
sf2d_draw_rectangle((x1<<4)+4-(offsetX<<1),(y1<<4)+4-(offsetY<<1),((x2-x1)<<4)-8,((y2-y1)<<4)-8, bgColor);
while(x1 < x2){
y1 = startY;
while(y1 < y2){
int xp=(x1<<4)-(offsetX<<1);
int yp=(y1<<4)-(offsetY<<1);
sf2d_draw_texture_part_scale(icons,xp,yp,getFrame(x1,x2,startX),200+getFrame(y1,y2,startY),8,8,2.0,2.0);
++y1;
}
++x1;
}
}
void renderDotsWithColor(int val, int x, int y,u8 bits, u32 color){
switch(val){
case 3: renderb(x,y,0,0,bits,color); return;
case 5: renderb(x+8,y,8,0,bits,color); return;
case 7: renderbc(x,y,0,0,16,8,bits,color); return;
case 10: renderb(x,y+8,0,8,bits,color); return;
case 11: renderbc(x,y,0,0,8,16,bits,color); return;
case 12: renderb(x+8,y+8,8,8,bits,color); return;
case 13: renderbc(x+8,y,8,0,8,16,bits,color); return;
case 14: renderbc(x,y+8,0,8,16,8,bits,color); return;
case 15: render16b(x,y,0,0,bits,color); return;
}
}
void renderRockDotsWithColor(int val, int x, int y, u32 color){
switch(val){
case 208: render16b(x,y,0,0,0,color); return;
case 16: renderb(x+8,y+8,8,8,0,color); return;
case 32: renderb(x,y+8,0,8,0,color); return;
case 48: renderb(x,y+8,0,8,0,color); return;
case 64: renderb(x,y,0,0,0,color); return;
case 80: renderbc(x,y,0,0,8,16,0,color);return;
case 96: renderbc(x+8,y,8,0,8,16,0,color);return;
case 112: renderbc(x,y+8,0,8,16,8,0,color);return;
case 128: renderbc(x,y,0,0,16,8,0,color);return;
case 144: renderb(x,y+8,0,8,0,color);renderbc(x+8,y,8,0,8,16,0,color); return;
case 160: renderb(x,y,0,0,0,color);renderbc(x+8,y,8,0,8,16,0,color); return;
case 176: renderb(x+8,y,8,0,0,color);renderbc(x,y,0,0,8,16,0,color); return;
case 192: renderb(x+8,y+8,8,8,0,color);renderbc(x,y,0,0,8,16,0,color); return;
case 4112: renderbc(x,y,0,0,8,16,0,color);return;
case 4128: renderbc(x,y+8,0,8,8,16,0,color);return;
case 4192: renderb(x,y,0,0,0,color); return;
case 8192: renderb(x,y+8,0,8,0,color); return;
case 8208: renderb(x+8,y+8,8,8,0,color); return;
case 8224: renderb(x+8,y+8,8,8,0,color); return;
case 8240: renderb(x+8,y,8,0,0,color); return;
case 8256: renderb(x,y+8,0,8,0,color); return;
case 8272: renderb(x+8,y,8,0,0,color); return;
case 8288: renderb(x,y,0,0,0,color); return;
case 8304: renderb(x+8,y,8,0,0,color);renderb(x,y+8,0,8,0,color); return;
case 8320: renderbc(x+8,y,8,0,8,16,0,color);return;
case 8336: renderbc(x,y,0,0,8,16,0,color);return;
case 8352: renderb(x,y,0,0,0,color); renderb(x+8,y+8,8,8,0,color); return;
case 8368: renderb(x+8,y,8,0,0,color); return;
case 8384: renderb(x,y+8,0,8,0,color); return;
case 8400: renderb(x,y,0,0,0,color); return;
case 8416: renderb(x+8,y+8,8,8,0,color); return;
}
}
void renderLights(){
renderLight(player.x,player.y,4*8);
int i;
for(i = 0; i < eManager.lastSlot[currentLevel]; ++i){
Entity e = eManager.entities[currentLevel][i];
if(e.type != ENTITY_FURNITURE) continue;
if(e.x > player.x-160 && e.y > player.y-125 && e.x<player.x+160 && e.y<player.y+125) renderLight(e.x,e.y,8*8);
}
};
/* The original software rendered version, it's bad for the framerate :( */
void renderLight(int x, int y, int r){
x-=offsetX;
y-=offsetY;
int x0 = x - r;
int x1 = x + r;
int y0 = y - r;
int y1 = y + r;
// The game's resolution is actually 200x120, the textures are all scaled up by 2.
if (x0 < 0) x0 = 0;
if (y0 < 0) y0 = 0;
if (x1 > 200) x1 = 200;
if (y1 > 120) y1 = 120;
int xx, yy;
for (yy = y0; yy < y1; yy++) {
int yd = yy - y;
yd = yd * yd;
for (xx = x0; xx < x1; xx++) {
int xd = xx - x;
int dist = xd * xd + yd;
if (dist <= r * r) sf2d_set_pixel(lightScreen, xx, yy, 0); // set transparent pixel
}
}
}
void renderLightScreen(){
sf2d_draw_texture_scale(lightScreen,0,0,2.0,2.0);
}
u8 checkSurrTiles8(int xt, int yt, int id){
u8 vt = 0;
if(getTile(xt,yt-1) == id) vt |= 1;
if(getTile(xt-1,yt) == id) vt |= 2;
if(getTile(xt+1,yt) == id) vt |= 4;
if(getTile(xt,yt+1) == id) vt |= 8;
if(getTile(xt-1,yt-1) == id) vt |= 16;
if(getTile(xt+1,yt-1) == id) vt |= 32;
if(getTile(xt-1,yt+1) == id) vt |= 64;
if(getTile(xt+1,yt+1) == id) vt |= 128;
return vt;
}
u8 checkSurrTiles4(int xt, int yt, int id){
u8 vt = 0;
if(getTile(xt,yt-1) == id) vt |= 1;
if(getTile(xt-1,yt) == id) vt |= 2;
if(getTile(xt+1,yt) == id) vt |= 4;
if(getTile(xt,yt+1) == id) vt |= 8;
return vt;
}
u8 v = 0;
u8 tData = 0;
void renderTile(int i, int x, int y){
int age=0;
switch(i){
case TILE_GRASS:
v = checkSurrTiles4(x >> 4,y >> 4, TILE_GRASS)
| checkSurrTiles4(x >> 4,y >> 4, TILE_TREE)
| checkSurrTiles4(x >> 4,y >> 4, TILE_FLOWER)
| checkSurrTiles4(x >> 4,y >> 4, TILE_SAPLING_TREE);
render16b(x,y,grassTable[v],80,0,0x69B569FF);
renderDotsWithColor(v, x, y, 0, 0x8ED38EFF);
break;
case TILE_TREE:
render16(x,y,treeTable[checkSurrTiles8(x >> 4,y >> 4, TILE_TREE)],16,0);
break;
case TILE_ROCK:
v = checkSurrTiles8(x >> 4,y >> 4, TILE_ROCK);
render16s(x,y,rockTable[v]+8192,0,0xFFFFFFFF);
renderRockDotsWithColor(rockTable[v], x, y, 0x949494FF);
break;
case TILE_HARDROCK:
v = checkSurrTiles8(x >> 4,y >> 4, TILE_HARDROCK);
render16s(x,y,rockTable[v]+8192,0,0xCFCFFFFF);
renderRockDotsWithColor(rockTable[v], x, y, 0x9494FFFF);
break;
case TILE_DIRT:
if(currentLevel>1)render16b(x,y,0,0,0,0x383838FF);
else render16b(x,y,0,0,0,0xA88F8FFF);
break;
case TILE_SAND:
v = checkSurrTiles4(x >> 4,y >> 4, TILE_SAND)
| checkSurrTiles4(x >> 4,y >> 4, TILE_CACTUS)
| checkSurrTiles4(x >> 4,y >> 4, TILE_SAPLING_CACTUS);
render16b(x,y,grassTable[v],80,0,0xF7F77BFF);
renderDotsWithColor(v, x, y, 0, 0xB7B75BFF);
break;
case TILE_WATER:
v = checkSurrTiles4(x >> 4,y >> 4, TILE_WATER)|checkSurrTiles4(x >> 4,y >> 4, TILE_HOLE);
render16b(x,y,grassTable[v],96,0,0x001DC1FF);
srand((tickCount + (x / 2 - y) * 4311)/10);
renderDotsWithColor(v, x, y, rand()&3, 0x6B6BFFFF);
break;
case TILE_LAVA:
v = checkSurrTiles4(x >> 4,y >> 4, TILE_LAVA)|checkSurrTiles4(x >> 4,y >> 4, TILE_HOLE);
render16b(x,y,grassTable[v],96,0,0xC11D00FF);
srand((tickCount + (x / 2 - y) * 4311)/10);
renderDotsWithColor(v, x, y, rand()&3, 0xFF6B6BFF);
break;
case TILE_HOLE:
render16b(x,y,grassTable[
checkSurrTiles4(x >> 4,y >> 4, TILE_HOLE)|
checkSurrTiles4(x >> 4,y >> 4, TILE_WATER)|
checkSurrTiles4(x >> 4,y >> 4, TILE_LAVA)
],96,0,0x383838FF);
break;
case TILE_CACTUS:
render16(x,y,48,0,0);
break;
case TILE_FLOWER:
render16(x,y,64,0,getData(x>>4,y>>4));
break;
case TILE_STAIRS_DOWN:
if(currentLevel == 0) renderTile(TILE_CLOUD,x,y);
render16(x,y,96,0,0);
break;
case TILE_STAIRS_UP:
render16(x,y,112,0,0);
break;
case TILE_IRONORE:
render16b(x,y,80,0,0,0xDFC8C8FF);
break;
case TILE_GOLDORE:
render16b(x,y,80,0,0,0xE5E8B9FF);
break;
case TILE_GEMORE:
render16b(x,y,80,0,0,0xDF98DEFF);
break;
case TILE_CLOUD:
render16b(x,y,grassTable[checkSurrTiles4(x >> 4,y >> 4, TILE_CLOUD)
| checkSurrTiles4(x >> 4,y >> 4, TILE_STAIRS_DOWN)
| checkSurrTiles4(x >> 4,y >> 4, TILE_CLOUDCACTUS)],80,0,0xFFFFFFFF);
break;
case TILE_CLOUDCACTUS:
renderTile(TILE_CLOUD,x,y);
render16(x,y,80,0,0);
break;
case TILE_SAPLING_TREE:
renderTile(TILE_GRASS,x,y);
render16(x,y,32,0,0);
break;
case TILE_SAPLING_CACTUS:
renderTile(TILE_SAND,x,y);
render16(x,y,32,0,0);
break;
case TILE_FARM:
render16(x,y,144,0,0);
break;
case TILE_WHEAT:
age = getData(x>>4,y>>4)/20;
if(age > 5) age = 5;
render16(x,y,160+(age<<4),0,0);
break;
}
}
void renderGui(){
int i;
for(i=0;i<10;++i){
if(i < player.p.health) render(i*8+1,1,168,152,0); else render(i*8+1,1,176,152,0);
if(i < player.p.stamina) render(i*8+1,10,184,152,0); else render(i*8+1,10,191,152,0);
}
}
void renderPlayer(){
if(player.p.isDead) return;
int xo = player.x - 8;
int yo = player.y - 8;
if(player.p.attackTimer > 0 && player.p.dir == 1){
renderc(xo,yo-4,16,160,16,8,0);
renderItemIcon(player.p.activeItem->id,player.p.activeItem->countLevel,xo+4,yo-4);
}
u8 walk = (player.p.walkDist >> 4) & 1;
bool swimming = isSwimming();
switch(player.p.dir){
case 0: // down
if(swimming)renderc(xo,yo+4,48,160+(((player.p.swimTimer>>4)&1)<<3),16,8,0);
else renderc(xo,yo+8,0,120+(player.p.isCarrying?16:0),16,8,walk==0?0:1);
renderc(xo,yo,0,112+(player.p.isCarrying?16:0),16,8,walk==0?0:1);
break;
case 1: // up
if(swimming)renderc(xo,yo+4,48,160+(((player.p.swimTimer>>4)&1)<<3),16,8,0);
else renderc(xo,yo+8,16,120+(player.p.isCarrying?16:0),16,8,walk==0?0:1);
renderc(xo,yo,16,112+(player.p.isCarrying?16:0),16,8,walk==0?0:1);
break;
case 2: // left
if(swimming)renderc(xo,yo+4,48,160+(((player.p.swimTimer>>4)&1)<<3),16,8,0);
else renderc(xo,yo+8,32+(walk<<4),120+(player.p.isCarrying?16:0),16,8,1);
renderc(xo,yo,32+(walk<<4),112+(player.p.isCarrying?16:0),16,8,1);
break;
case 3: // right
if(swimming)renderc(xo,yo+4,48,160+(((player.p.swimTimer>>4)&1)<<3),16,8,0);
else renderc(xo,yo+8,32+(walk<<4),120+(player.p.isCarrying?16:0),16,8,0);
renderc(xo,yo,32+(walk<<4),112+(player.p.isCarrying?16:0),16,8,0);
break;
}
if(player.p.isCarrying){
renderFurniture(player.p.activeItem->id, xo, yo-12);
}
if(player.p.attackTimer > 0){
switch(player.p.dir){
case 0:
renderc(xo-player.p.ax,yo-player.p.ay+12,16,168,16,8,0);
renderItemIcon(player.p.activeItem->id,player.p.activeItem->countLevel, xo+4,yo+12);
break;
case 2:
renderc(xo-player.p.ax-4,yo-player.p.ay,32,160,8,16,0);
renderItemIcon(player.p.activeItem->id,player.p.activeItem->countLevel, xo-4,yo+4);
break;
case 3:
renderc(xo-player.p.ax+12,yo-player.p.ay,40,160,8,16,0);
renderItemIcon(player.p.activeItem->id,player.p.activeItem->countLevel, xo+12,yo+4);
break;
}
}
}
void renderBackground(int xScroll, int yScroll){
int xo = xScroll >> 4;
int yo = yScroll >> 4;
int x,y;
for (x = xo;x <= 13 + xo; ++x) {
for (y = yo;y <= 8 + yo; ++y)renderTile(getTile(x,y),x << 4,y << 4);
}
}
char * fontChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789.,!?'\"-+=/\\%()<>:; ";
void drawText(char * msg, u32 x, u32 y){
int i = 0;
x-=offsetX<<1;
y-=offsetY<<1;
for(i = 0; i<strlen(msg); ++i){
int ix = strchr(fontChars, toupper((unsigned char)msg[i]))-fontChars;
int iy = ix >> 5;
if (ix >= 0) {
sf2d_draw_texture_part(font,x + i * 12,y,(ix&31)*12,16+(iy*12),12,12);
}
}
}
void drawSizedText(char * msg, u32 x, u32 y, float size){
int i = 0;
for(i = 0; i<strlen(msg); ++i){
int ix = strchr(fontChars, toupper((unsigned char)msg[i]))-fontChars;
int iy = ix >> 5;
if (ix >= 0) {
sf2d_draw_texture_part_scale(font,(x + i * 8) * size,y,(ix&31)<<3,iy<<3,8,8,size,size);
}
}
}
void drawTextColor(char * msg, u32 x, u32 y, u32 color){
int i = 0;
x-=offsetX<<1;
y-=offsetY<<1;
for(i = 0; i<strlen(msg); ++i){
int ix = strchr(fontChars, toupper((unsigned char)msg[i]))-fontChars;
int iy = ix >> 5;
if (ix >= 0) {
sf2d_draw_texture_part_blend(font,x + i * 12,y,(ix&31)*12,16+(iy*12),12,12, color);
}
}
}
// Changes text color after the first space.
void drawTextColorSpecial(char * msg, u32 x, u32 y, u32 color, u32 color2){
int i = 0;
x-=offsetX<<1;
y-=offsetY<<1;
bool sOver = false;
for(i = 0; i<strlen(msg); ++i){
int ix = strchr(fontChars, toupper((unsigned char)msg[i]))-fontChars;
if(msg[i] == 32) sOver = true;
int iy = ix >> 5;
if (ix >= 0) {
if(sOver)sf2d_draw_texture_part_blend(font,x + i * 12,y,(ix&31)*12,16+(iy*12),12,12, color2);
else sf2d_draw_texture_part_blend(font,x + i * 12,y,(ix&31)*12,16+(iy*12),12,12, color);
}
}
}
void drawSizedTextColor(char * msg, int x, int y, float size, u32 color){
int i;
for(i = 0; i<strlen(msg); ++i){
int ix = strchr(fontChars, toupper((unsigned char)msg[i]))-fontChars;
int iy = ix >> 5;
if (ix >= 0) sf2d_draw_texture_part_scale_blend(font,(x + i * 8) * size,y*size,(ix&31)<<3,iy<<3,8,8,size,size,color);
}
}
void renderFurniture(int itemID, int x, int y){
switch(itemID){
case ITEM_ANVIL: render16(x,y,64,128,0); break;
case ITEM_CHEST: render16(x,y,80,128,0); break;
case ITEM_OVEN: render16(x,y,96,128,0); break;
case ITEM_FURNACE: render16(x,y,112,128,0); break;
case ITEM_WORKBENCH: render16(x,y,128,128,0); break;
case ITEM_LANTERN: render16(x,y,144,128,0); break;
}
}
char ertxt[20];
void renderEntity(Entity* e, int x, int y){
switch(e->type){
case ENTITY_ITEM:
if (e->entityItem.age >= 520) if (e->entityItem.age / 6 % 2 == 0) return;
renderItemIcon2(e->entityItem.item.id,e->entityItem.item.countLevel, x-4, y-4, (int)e->entityItem.zz);
break;
case ENTITY_FURNITURE: renderFurniture(e->entityFurniture.itemID, x-8, y-8); break;
case ENTITY_ZOMBIE:
switch(e->zombie.dir){
case 0: // down
render16b(x-8,y-8,64,112,((e->zombie.walkDist>>4)&1)==0?0:1,e->zombie.color);
break;
case 1: // up
render16b(x-8,y-8,80,112,((e->zombie.walkDist>>4)&1)==0?0:1,e->zombie.color);
break;
case 2: // left
render16b(x-8,y-8,96+(((e->zombie.walkDist>>4)&1)<<4),112,1,e->zombie.color);
break;
case 3: // right
render16b(x-8,y-8,96+(((e->zombie.walkDist>>4)&1)<<4),112,0,e->zombie.color);
break;
}
break;
case ENTITY_SLIME:
render16b(x-8,y-8-(e->slime.jumpTime>0?4:0),128+(e->slime.jumpTime>0?16:0),112,0,e->slime.color);
break;
case ENTITY_AIRWIZARD:
e->wizard.spriteAdjust = 0;
if(e->wizard.health < 200){ if (tickCount / 4 % 3 < 2) e->wizard.spriteAdjust = 16; }
else if(e->wizard.health < 1000){ if (tickCount / 5 % 4 < 2) e->wizard.spriteAdjust = 16; }
switch(e->wizard.dir){
case 0: // down
render16(x-8,y-8,160,112+e->wizard.spriteAdjust,((e->wizard.walkDist>>4)&1)==0?0:1);
break;
case 1: // up
render16(x-8,y-8,176,112+e->wizard.spriteAdjust,((e->wizard.walkDist>>4)&1)==0?0:1);
break;
case 2: // left
render16(x-8,y-8,192+(((e->wizard.walkDist>>4)&1)<<4),112+e->wizard.spriteAdjust,1);
break;
case 3: // right
render16(x-8,y-8,192+(((e->wizard.walkDist>>4)&1)<<4),112+e->wizard.spriteAdjust,0);
break;
}
break;
case ENTITY_TEXTPARTICLE:
x-=offsetX;
y-=offsetY;
drawSizedTextColor(e->textParticle.text,x+1,y-(int)e->textParticle.zz+1,2,0xFF);
drawSizedTextColor(e->textParticle.text,x,y-(int)e->textParticle.zz,2,e->textParticle.color);
break;
case ENTITY_SMASHPARTICLE: render16(x,y,0,160,0); break;
case ENTITY_SPARK:
if (e->spark.age >= 200) if (e->spark.age / 6 % 2 == 0) return;
renderr(x,y,200,152,0,e->spark.age*0.0349);
break;
}
}
void renderEntities(int x, int y, EntityManager* em){
int i;
for(i = 0; i < em->lastSlot[currentLevel]; ++i){
Entity e = em->entities[currentLevel][i];
if(e.x > x-200 && e.y > y-125 && e.x<x+200 && e.y<y+125) renderEntity(&e, e.x, e.y);
}
}
void renderItemList(Inventory * inv,int xo, int yo, int x1, int y1, int selected){
// If lastSlot is 0, then there are no items are in the inventory.
bool drawCursor = true;
if(selected < 0){
drawCursor = false;
selected = 0;
}
int w = x1 - xo;
int h = y1 - yo - 2;
int i1 = inv->lastSlot;
if (i1 > h) i1 = h;
int io = selected - h / 2;
if (io > inv->lastSlot - h) io = inv->lastSlot - h;
if (io < 0) io = 0;
int i;
for(i = 0; i < i1; ++i) renderItemWithText(&inv->items[i+io], (1 + xo) << 4, (i + 1 + yo) << 4);
if(drawCursor){
int yy = selected + 1 - io + yo;
sf2d_draw_rectangle((xo<<4)-(offsetX<<1),(yy<<4)-(offsetY<<1),12,12,0xFF);
drawText(">", (xo << 4), yy << 4);
sf2d_draw_rectangle(((xo+w)<<4)-12-(offsetX<<1),(yy<<4)-(offsetY<<1),12,12,0xFF);
drawText("<", ((xo+w)<<4)-12, yy<<4);
}
}
void renderRecipes(RecipeManager * r,int xo, int yo, int x1, int y1, int selected){
int size = r->size;
if(size < 1) return;
if(selected < 0) selected = 0;
int w = x1 - xo;
int h = y1 - yo - 2;
int i1 = size;
if (i1 > h) i1 = h;
int io = selected - h / 2;
if (io > size - h) io = size - h;
if (io < 0) io = 0;
int i, col;
for(i = 0; i < i1; ++i){
int x = (1 + xo) << 4, y = (i + 1 + yo) << 4;
renderItemIcon(r->recipes[i+io].itemResult,r->recipes[i+io].itemAmountLevel,x>>1,y>>1);
if(r->recipes[i+io].canCraft) col = 0xFFFFFFFF;
else col = 0x7F7F7FFF;
drawTextColor(getBasicItemName(r->recipes[i+io].itemResult,r->recipes[i+io].itemAmountLevel),x+18,y+2,col);
}
int yy = selected + 1 - io + yo;
sf2d_draw_rectangle(xo<<4,yy<<4,12,12,0xFF);
drawText(">", xo << 4, yy << 4);
sf2d_draw_rectangle(((xo+w)<<4)-12,yy<<4,12,12,0xFF);
drawText("<", ((xo+w)<<4)-12, yy<<4);
}
void renderItemWithText(Item* item, int x, int y){
renderItemIcon(item->id,item->countLevel,x>>1,y>>1);
if(item->onlyOne) drawText(getItemName(item->id,item->countLevel),x+18,y+2);
else drawTextColorSpecial(getItemName(item->id,item->countLevel),x+18,y+2,0xD2D2D2FF,0xFFFFFFFF);
}
void renderItemIcon2(int itemID, int countLevel, int x, int y, int z){
switch(itemID){
case ITEM_NULL: return;
case TOOL_SHOVEL: renderb(x,y,countLevel*8,144,0,0xFF); break;
case TOOL_HOE: renderb(x,y,40+countLevel*8,144,0,0xFF); break;
case TOOL_SWORD: renderb(x,y,80+countLevel*8,144,0,0xFF); break;
case TOOL_PICKAXE: renderb(x,y,120+countLevel*8,144,0,0xFF); break;
case TOOL_AXE: renderb(x,y,160+countLevel*8,144,0,0xFF); break;
case ITEM_ANVIL: renderb(x,y,120,152,0,0xFF); break;
case ITEM_CHEST: renderb(x,y,128,152,0,0xFF); break;
case ITEM_OVEN: renderb(x,y,136,152,0,0xFF); break;
case ITEM_FURNACE: renderb(x,y,144,152,0,0xFF); break;
case ITEM_WORKBENCH: renderb(x,y,152,152,0,0xFF); break;
case ITEM_LANTERN: renderb(x,y,160,152,0,0xFF); break;
case ITEM_POWGLOVE: renderb(x,y,56,152,0,0xFF); break;
case ITEM_FLOWER: renderb(x,y,0,152,0,0xFF); break;
case ITEM_WOOD: renderb(x,y,8,152,0,0xFF); break;
case ITEM_STONE: renderb(x,y,16,152,0,0xFF); break;
case ITEM_SAND: renderb(x,y,16,152,0,0xFF); break;
case ITEM_DIRT: renderb(x,y,16,152,0,0xFF); break;
case ITEM_CLOUD: renderb(x,y,16,152,0,0xFF); break;
case ITEM_ACORN: renderb(x,y,24,152,0,0xFF); break;
case ITEM_CACTUS: renderb(x,y,32,152,0,0xFF); break;
case ITEM_SEEDS: renderb(x,y,40,152,0,0xFF); break;
case ITEM_WHEAT: renderb(x,y,48,152,0,0xFF); break;
case ITEM_FLESH: renderb(x,y,64,152,0,0xFF); break;
case ITEM_BREAD: renderb(x,y,72,152,0,0xFF); break;
case ITEM_APPLE: renderb(x,y,80,152,0,0xFF); break;
case ITEM_SLIME: renderb(x,y,88,152,0,0xFF); break;
case ITEM_COAL: renderb(x,y,88,152,0,0xFF); break;
case ITEM_IRONORE: renderb(x,y,88,152,0,0xFF); break;
case ITEM_GOLDORE: renderb(x,y,88,152,0,0xFF); break;
case ITEM_IRONINGOT: renderb(x,y,96,152,0,0xFF); break;
case ITEM_GOLDINGOT: renderb(x,y,96,152,0,0xFF); break;
case ITEM_GLASS: renderb(x,y,104,152,0,0xFF); break;
case ITEM_GEM: renderb(x,y,112,152,0,0xFF); break;
}
y-=z;
renderItemIcon(itemID, countLevel, x, y);
}
void renderItemIcon(int itemID,int countLevel, int x, int y){
switch(itemID){
case ITEM_NULL: return;
case TOOL_SHOVEL: render(x,y,countLevel*8,144,0); break;
case TOOL_HOE: render(x,y,40+countLevel*8,144,0); break;
case TOOL_SWORD: render(x,y,80+countLevel*8,144,0); break;
case TOOL_PICKAXE: render(x,y,120+countLevel*8,144,0); break;
case TOOL_AXE: render(x,y,160+countLevel*8,144,0); break;
case ITEM_ANVIL: render(x,y,120,152,0); break;
case ITEM_CHEST: render(x,y,128,152,0); break;
case ITEM_OVEN: render(x,y,136,152,0); break;
case ITEM_FURNACE: render(x,y,144,152,0); break;
case ITEM_WORKBENCH: render(x,y,152,152,0); break;
case ITEM_LANTERN: render(x,y,160,152,0); break;
case ITEM_POWGLOVE: render(x,y,56,152,0); break;
case ITEM_FLOWER: render(x,y,0,152,0); break;
case ITEM_WOOD: render(x,y,8,152,0); break;
case ITEM_STONE: renderb(x,y,16,152,0,0xCFCFCFFF); break;
case ITEM_SAND: renderb(x,y,16,152,0,0xF7F77BFF); break;
case ITEM_DIRT: renderb(x,y,16,152,0,0xAF9781FF); break;
case ITEM_CLOUD: renderb(x,y,16,152,0,0xFFFFFFFF); break;
case ITEM_ACORN: render(x,y,24,152,0); break;
case ITEM_CACTUS: render(x,y,32,152,0); break;
case ITEM_SEEDS: render(x,y,40,152,0); break;
case ITEM_WHEAT: render(x,y,48,152,0); break;
case ITEM_FLESH: render(x,y,64,152,0); break;
case ITEM_BREAD: render(x,y,72,152,0); break;
case ITEM_APPLE: render(x,y,80,152,0); break;
case ITEM_SLIME: renderb(x,y,88,152,0,0x4DC04DFF); break;
case ITEM_COAL: renderb(x,y,88,152,0,0x383838FF); break;
case ITEM_IRONORE: renderb(x,y,88,152,0,0xBC9999FF); break;
case ITEM_GOLDORE: renderb(x,y,88,152,0,0xCECE77FF); break;
case ITEM_IRONINGOT: renderb(x,y,96,152,0,0xDFC8C8FF); break;
case ITEM_GOLDINGOT: renderb(x,y,96,152,0,0xEAEABCFF); break;
case ITEM_GLASS: render(x,y,104,152,0); break;
case ITEM_GEM: render(x,y,112,152,0); break;
}
}
void defineTables(){
int i = 0;
for(i = 256;i > 0;--i){
// Creates the lookup table for the tree tile.
if((i&255)==255) treeTable[i] = 208;
else if((i&239)==239) treeTable[i] = 144;
else if((i&191)==191) treeTable[i] = 160;
else if((i&127)==127) treeTable[i] = 176;
else if((i&223)==223) treeTable[i] = 192;
else if((i&206)==206) treeTable[i] = 112;
else if((i&55)==55) treeTable[i] = 128;
else if((i&173)==173) treeTable[i] = 96;
else if((i&91)==91) treeTable[i] = 80;
else if((i&159)==159) treeTable[i] = 224;
else if((i&111)==111) treeTable[i] = 240;
else if((i&19)==19) treeTable[i] = 64;
else if((i&37)==37) treeTable[i] = 48;
else if((i&74)==74) treeTable[i] = 32;
else if((i&140)==140) treeTable[i] = 16;
}
/*
boolean up = i & 1
boolean left = i & 2
boolean right = i & 4
boolean down = i & 8
boolean up-left = i & 16
boolean up-right = i & 32
boolean down-left = i & 64
boolean down-right = i & 128
*/
for(i = 256;i > 0;--i){
// Creates the lookup table for the rock tile.
if((i&255)==255) rockTable[i] = 208;
else if((i&239)==239) rockTable[i] = 144;
else if((i&191)==191) rockTable[i] = 160;
else if((i&127)==127) rockTable[i] = 176;
else if((i&223)==223) rockTable[i] = 192;
else if((i&207)==207) rockTable[i] = 256*16+32;
else if((i&63)==63) rockTable[i] = 256*16+16;
else if((i&206)==206) rockTable[i] = 112;
else if((i&95)==95) rockTable[i] = 256*32+144;
else if((i&159)==159) rockTable[i] = 256*32+160;
else if((i&31)==31) rockTable[i] = 256*32+208;
else if((i&55)==55) rockTable[i] = 128;
else if((i&175)==175) rockTable[i] = 256*32+128;
else if((i&143)==143) rockTable[i] = 256*32+224;
else if((i&173)==173) rockTable[i] = 96;
else if((i&111)==111) rockTable[i] = 256*32+112;
else if((i&47)==47) rockTable[i] = 256*32+48;
else if((i&45)==45) rockTable[i] = 256*32+176;
else if((i&79)==79) rockTable[i] = 256*32+192;
else if((i&23)==23) rockTable[i] = 256*32+96;
else if((i&91)==91) rockTable[i] = 80;
else if((i&27)==27) rockTable[i] = 256*16+96;
else if((i&19)==19) rockTable[i] = 64;
else if((i&75)==75) rockTable[i] = 256*32;
else if((i&141)==141) rockTable[i] = 256*32+16;
else if((i&142)==142) rockTable[i] = 256*32+32;
else if((i&78)==78) rockTable[i] = 256*32+64;
else if((i&39)==39) rockTable[i] = 256*32+80;
else if((i&37)==37) rockTable[i] = 48;
else if((i&74)==74) rockTable[i] = 32;
else if((i&140)==140) rockTable[i] = 16;
else if((i&15)==15) rockTable[i] = 256*16+112;
else if((i&11)==11) rockTable[i] = 256*16+192;
else if((i&13)==13) rockTable[i] = 256*16+208;
else if((i&14)==14) rockTable[i] = 256*16+224;
else if((i&7)==7) rockTable[i] = 256*16+240;
else if((i&12)==12) rockTable[i] = 256*16+128;
else if((i&10)==10) rockTable[i] = 256*16+144;
else if((i&5)==5) rockTable[i] = 256*16+160;
else if((i&3)==3) rockTable[i] = 256*16+176;
else if((i&9)==9) rockTable[i] = 256*16;
else if((i&6)==6) rockTable[i] = 256*16+48;
else if((i&8)==8) rockTable[i] = 224;
else if((i&4)==4) rockTable[i] = 256*16+64;
else if((i&2)==2) rockTable[i] = 256*16+80;
else if((i&1)==1) rockTable[i] = 240;
}
// Lookup table for the grass/sand tile.
grassTable[1] = 192;
grassTable[2] = 160;
grassTable[3] = 64;
grassTable[4] = 144;
grassTable[5] = 48;
grassTable[6] = 224;
grassTable[7] = 128;
grassTable[8] = 176;
grassTable[9] = 240;
grassTable[10] = 32;
grassTable[11] = 80;
grassTable[12] = 16;
grassTable[13] = 96;
grassTable[14] = 112;
grassTable[15] = 208;
}

54
source/Render.h Normal file
View file

@ -0,0 +1,54 @@
#pragma once
#include <3ds.h>
#include <sf2d.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "Globals.h"
#include "MapGen.h"
sf2d_texture *icons;
sf2d_texture *font;
sf2d_texture *lightScreen;
int offsetX, offsetY;
void render(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits);
void renderb(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color);
void renderr(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits,float rotate);
void renderc(s32 xp, s32 yp, u32 xTile, u32 yTile,int sizeX, int sizeY, u8 bits);
void renderbc(s32 xp, s32 yp, u32 xTile, u32 yTile,int sizeX, int sizeY, u8 bits, u32 color);
void render16(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits);
void render16c(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits,float scaleX,float scaleY);
void render16b(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits,u32 color);
void render16s(s32 xp, s32 yp, u32 tile, u8 bits,u32 color);
void renderTitle(int x, int y);
void renderFrame(int x1, int y1, int x2, int y2, u32 bgColor);
void renderTile(int i, int x, int y);
void renderBackground(int xScroll, int yScroll);
void renderButtonIcon(u32 icon, int x, int y, float scale);
void renderLights();
void renderLight(int x, int y, int r);
void renderLightScreen();
void renderGui();
void renderPlayer();
void drawText(char * msg, u32 x, u32 y);
void drawSizedText(char * msg, u32 x, u32 y, float size);
void drawTextColor(char * msg, u32 x, u32 y, u32 color);
void drawTextColorSpecial(char * msg, u32 x, u32 y, u32 color, u32 color2);
void drawSizedTextColor(char * msg, int x, int y, float size, u32 color);
void renderFurniture(int itemID, int x, int y);
void renderEntity(Entity* e, int x, int y);
void renderEntities(int x, int y, EntityManager* em);
void renderRecipes(RecipeManager * r,int xo, int yo, int x1, int y1, int selected);
void renderItemList(Inventory * inv,int xo, int yo, int x1, int y1, int selected);
void renderItemWithText(Item* item, int x, int y);
void renderItemIcon(int itemID, int countLevel, int x, int y);
void renderItemIcon2(int itemID, int countLevel, int x, int y, int z);
void defineTables();

251
source/SaveLoad.c Normal file
View file

@ -0,0 +1,251 @@
#include "SaveLoad.h"
s16 calculateImportantEntites(EntityManager * eManager, int level){
int i;
s16 count = 0;
for(i = 0; i < eManager->lastSlot[level]; ++i){
switch(eManager->entities[level][i].type){
case ENTITY_AIRWIZARD:
case ENTITY_SLIME:
case ENTITY_ZOMBIE:
case ENTITY_ITEM:
case ENTITY_FURNITURE:
count++;
break;
}
}
return count;
}
bool entityIsImportant(Entity * e){
switch(e->type){
case ENTITY_AIRWIZARD:
case ENTITY_SLIME:
case ENTITY_ZOMBIE:
case ENTITY_ITEM:
case ENTITY_FURNITURE:
return true;
default:
return false;
}
}
void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData){
FILE * file = fopen(filename, "wb");
int i,j;
// Player Data
fwrite(&player->p.score, sizeof(int), 1, file);
fwrite(&player->p.hasWonSaved, sizeof(bool), 1, file);
fwrite(&player->p.health, sizeof(s16), 1, file);
fwrite(&player->x, sizeof(s16), 1, file);
fwrite(&player->y, sizeof(s16), 1, file);
fwrite(&currentLevel, sizeof(s8), 1, file);
// Inventory Data
fwrite(&eManager->nextInv, sizeof(s16), 1, file); // write amount of inventories.
for(i = 0; i < eManager->nextInv; ++i) {
fwrite(&eManager->invs[i].lastSlot, sizeof(s16), 1, file); // write amount of items in inventory;
for(j = 0; j < eManager->invs[i].lastSlot; ++j) {
fwrite(&eManager->invs[i].items[j].id, sizeof(s16), 1, file); // write ID of item
fwrite(&eManager->invs[i].items[j].countLevel, sizeof(s16), 1, file); // write count/level of item
fwrite(&eManager->invs[i].items[j].onlyOne, sizeof(bool), 1, file);
if(eManager->invs[i].items[j].id == ITEM_CHEST){
int invIndex = eManager->invs[i].items[j].chestPtr - eManager->invs;
fwrite(&invIndex, sizeof(int), 1, file);
}
}
}
// Entity Data
for(i = 0; i < 5; ++i){
int amount = calculateImportantEntites(eManager,i);
fwrite(&amount, sizeof(s16), 1, file); // read amount of entities in level.
for(j = 0; j < eManager->lastSlot[i]; ++j){
if(!entityIsImportant(&eManager->entities[i][j])) continue;
fwrite(&eManager->entities[i][j].type, sizeof(s16), 1, file); // write entity's type ID
fwrite(&eManager->entities[i][j].x, sizeof(s16), 1, file); // write entity's x coordinate
fwrite(&eManager->entities[i][j].y, sizeof(s16), 1, file); // write entity's y coordinate
switch(eManager->entities[i][j].type){
case ENTITY_AIRWIZARD:
fwrite(&eManager->entities[i][j].wizard.health, sizeof(s16), 1, file);
break;
case ENTITY_SLIME:
fwrite(&eManager->entities[i][j].slime.health, sizeof(s16), 1, file);
fwrite(&eManager->entities[i][j].slime.lvl, sizeof(s8), 1, file);
break;
case ENTITY_ZOMBIE:
fwrite(&eManager->entities[i][j].zombie.health, sizeof(s16), 1, file);
fwrite(&eManager->entities[i][j].zombie.lvl, sizeof(s8), 1, file);
break;
case ENTITY_ITEM:
fwrite(&eManager->entities[i][j].entityItem.item.id, sizeof(s16), 1, file);
fwrite(&eManager->entities[i][j].entityItem.item.countLevel, sizeof(s16), 1, file);
fwrite(&eManager->entities[i][j].entityItem.age, sizeof(s16), 1, file);
break;
case ENTITY_FURNITURE:
fwrite(&eManager->entities[i][j].entityFurniture.itemID, sizeof(s16), 1, file);
int invIndex = eManager->entities[i][j].entityFurniture.inv - eManager->invs;
fwrite(&invIndex, sizeof(int), 1, file);
break;
}
}
}
// Map Data
fwrite(map, sizeof(u8), 128*128*5, file); // Map Tile IDs, 128*128*5 bytes = 80KB
fwrite(mapData, sizeof(u8), 128*128*5, file); // Map Tile Data (Damage done to trees/rocks, age of wheat & saplings, etc). 80KB
fclose(file);
}
int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData){
FILE * file;
int i,j;
if ((file = fopen(filename, "rb"))){
fread(&player->p.score, sizeof(int), 1, file);
fread(&player->p.hasWonSaved, sizeof(bool), 1, file);
fread(&player->p.health, sizeof(s16), 1, file);
fread(&player->x, sizeof(s16), 1, file);
fread(&player->y, sizeof(s16), 1, file);
fread(&currentLevel, sizeof(s8), 1, file);
fread(&eManager->nextInv, sizeof(s16), 1, file);
for(i = 0; i < eManager->nextInv; ++i) {
fread(&eManager->invs[i].lastSlot, sizeof(s16), 1, file); // read amount of items in inventory;
for(j = 0; j < eManager->invs[i].lastSlot; ++j) {
fread(&eManager->invs[i].items[j].id, sizeof(s16), 1, file); // write ID of item
fread(&eManager->invs[i].items[j].countLevel, sizeof(s16), 1, file); // write count/level of item
fread(&eManager->invs[i].items[j].onlyOne, sizeof(bool), 1, file);
eManager->invs[i].items[j].invPtr = (int*)&eManager->invs[i]; // setup Inventory pointer
eManager->invs[i].items[j].slotNum = j; // setup slot number
if(eManager->invs[i].items[j].id == ITEM_CHEST){ // for chest item specifically.
int invIndex;
fread(&invIndex, sizeof(int), 1, file);
eManager->invs[i].items[j].chestPtr = (Inventory*)&eManager->invs[invIndex]; // setup chest inventory pointer.
}
}
}
for(i = 0; i < 5; ++i){
fread(&eManager->lastSlot[i], sizeof(s16), 1, file); // read amount of entities in level.
for(j = 0; j < eManager->lastSlot[i]; ++j){
fread(&eManager->entities[i][j].type, sizeof(s16), 1, file); // read entity's type ID
fread(&eManager->entities[i][j].x, sizeof(s16), 1, file); // read entity's x coordinate
fread(&eManager->entities[i][j].y, sizeof(s16), 1, file); // read entity's y coordinate
eManager->entities[i][j].slotNum = j;
switch(eManager->entities[i][j].type){
case ENTITY_SMASHPARTICLE:
eManager->entities[i][j].level = i;
eManager->entities[i][j].smashParticle.age = 300;
eManager->entities[i][j].canPass = true;
break;
case ENTITY_TEXTPARTICLE:
eManager->entities[i][j].level = i;
eManager->entities[i][j].canPass = true;
eManager->entities[i][j].textParticle.age = 59;
eManager->entities[i][j].textParticle.text = NULL;
eManager->entities[i][j].textParticle.xx = eManager->entities[i][j].x;
eManager->entities[i][j].textParticle.yy = eManager->entities[i][j].y;
eManager->entities[i][j].textParticle.zz = 2;
eManager->entities[i][j].textParticle.xa = 0;
eManager->entities[i][j].textParticle.ya = 0;
eManager->entities[i][j].textParticle.za = 0;
break;
case ENTITY_SPARK:
eManager->entities[i][j].level = i;
eManager->entities[i][j].spark.age = 300;
break;
case ENTITY_AIRWIZARD:
fread(&eManager->entities[i][j].wizard.health, sizeof(s16), 1, file);
eManager->entities[i][j].level = i;
eManager->entities[i][j].hurtTime = 0;
eManager->entities[i][j].xKnockback = 0;
eManager->entities[i][j].yKnockback = 0;
eManager->entities[i][j].wizard.dir = 0;
eManager->entities[i][j].wizard.attackDelay = 0;
eManager->entities[i][j].wizard.attackTime = 0;
eManager->entities[i][j].wizard.attackType = 0;
eManager->entities[i][j].wizard.xa = 0;
eManager->entities[i][j].wizard.ya = 0;
eManager->entities[i][j].xr = 4;
eManager->entities[i][j].yr = 3;
eManager->entities[i][j].canPass = true;
break;
case ENTITY_SLIME:
fread(&eManager->entities[i][j].slime.health, sizeof(s16), 1, file);
fread(&eManager->entities[i][j].slime.lvl, sizeof(s8), 1, file);
eManager->entities[i][j].level = i;
eManager->entities[i][j].hurtTime = 0;
eManager->entities[i][j].xKnockback = 0;
eManager->entities[i][j].yKnockback = 0;
eManager->entities[i][j].slime.xa = 0;
eManager->entities[i][j].slime.ya = 0;
eManager->entities[i][j].slime.dir = 0;
eManager->entities[i][j].xr = 4;
eManager->entities[i][j].yr = 3;
eManager->entities[i][j].canPass = false;
switch(eManager->entities[i][j].slime.lvl){
case 2: eManager->entities[i][j].slime.color = 0xCC8282FF; break;
case 3: eManager->entities[i][j].slime.color = 0xEFEFEFFF; break;
case 4: eManager->entities[i][j].slime.color = 0x6262AAFF; break;
default: eManager->entities[i][j].slime.color = 0x95DB95FF; break;
}
break;
case ENTITY_ZOMBIE:
fread(&eManager->entities[i][j].zombie.health, sizeof(s16), 1, file);
fread(&eManager->entities[i][j].zombie.lvl, sizeof(s8), 1, file);
eManager->entities[i][j].level = i;
eManager->entities[i][j].hurtTime = 0;
eManager->entities[i][j].xKnockback = 0;
eManager->entities[i][j].yKnockback = 0;
eManager->entities[i][j].zombie.dir = 0;
eManager->entities[i][j].xr = 4;
eManager->entities[i][j].yr = 3;
eManager->entities[i][j].canPass = false;
switch(eManager->entities[i][j].zombie.lvl){
case 2: eManager->entities[i][j].zombie.color = 0xCC8282FF; break;
case 3: eManager->entities[i][j].zombie.color = 0xEFEFEFFF; break;
case 4: eManager->entities[i][j].zombie.color = 0x6262AAFF; break;
default: eManager->entities[i][j].zombie.color = 0x95DB95FF; break;
}
break;
case ENTITY_ITEM:
//eManager->entities[i][j].entityItem.item = newItem(0,0);
fread(&eManager->entities[i][j].entityItem.item.id, sizeof(s16), 1, file);
fread(&eManager->entities[i][j].entityItem.item.countLevel, sizeof(s16), 1, file);
fread(&eManager->entities[i][j].entityItem.age, sizeof(s16), 1, file);
eManager->entities[i][j].level = i;
eManager->entities[i][j].entityItem.age = 0;
eManager->entities[i][j].xr = 3;
eManager->entities[i][j].yr = 3;
eManager->entities[i][j].canPass = false;
eManager->entities[i][j].entityItem.xx = eManager->entities[i][j].x;
eManager->entities[i][j].entityItem.yy = eManager->entities[i][j].y;
eManager->entities[i][j].entityItem.zz = 2;
eManager->entities[i][j].entityItem.xa = 0;
eManager->entities[i][j].entityItem.ya = 0;
eManager->entities[i][j].entityItem.za = 0;
break;
case ENTITY_FURNITURE:
fread(&eManager->entities[i][j].entityFurniture.itemID, sizeof(s16), 1, file);
int invIndex;
fread(&invIndex, sizeof(int), 1, file);
eManager->entities[i][j].entityFurniture.inv = &eManager->invs[invIndex];
eManager->entities[i][j].xr = 3;
eManager->entities[i][j].yr = 3;
eManager->entities[i][j].canPass = false;
if(eManager->entities[i][j].entityFurniture.itemID == ITEM_LANTERN) eManager->entities[i][j].entityFurniture.r = 8;
break;
}
}
}
fread(map, sizeof(u8), 128*128*5, file);
fread(mapData, sizeof(u8), 128*128*5, file);
fclose(file);
return 0;
}
return 1;
}

7
source/SaveLoad.h Normal file
View file

@ -0,0 +1,7 @@
#pragma once
#include <stdio.h>
#include <string.h>
#include "Entity.h"
void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData);
int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData);

27
source/Sound.c Normal file
View file

@ -0,0 +1,27 @@
#include "Sound.h"
void loadSound(Sound * snd, char * filename){
FILE *file = fopen(filename, "rb");
if(file != NULL){
fseek(file, 0, SEEK_END);
snd->size = ftell(file);
fseek(file, 0, SEEK_SET);
snd->buffer = linearAlloc(snd->size);
fread(snd->buffer, 1, snd->size, file);
}
fclose(file);
}
void playSound(Sound snd){
csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 44100, 1, 0, snd.buffer, snd.buffer, snd.size);
}
void freeSounds(){
linearFree(snd_playerHurt.buffer);
linearFree(snd_playerDeath.buffer);
linearFree(snd_monsterHurt.buffer);
linearFree(snd_test.buffer);
linearFree(snd_pickup.buffer);
linearFree(snd_bossdeath.buffer);
linearFree(snd_craft.buffer);
}

23
source/Sound.h Normal file
View file

@ -0,0 +1,23 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <3ds.h>
typedef struct {
u32 size;
u8 * buffer;
} Sound;
void loadSound(Sound * snd, char * filename);
void playSound(Sound snd);
void freeSounds();
Sound snd_playerHurt;
Sound snd_playerDeath;
Sound snd_monsterHurt;
Sound snd_test;
Sound snd_pickup;
Sound snd_bossdeath;
Sound snd_craft;

279
source/main.c Normal file
View file

@ -0,0 +1,279 @@
#include <3ds.h>
#include <sf2d.h>
#include <sfil.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include "icons2_png.h"
#include "Font_png.h"
#include "Globals.h"
#include "Render.h"
#include "MapGen.h"
#include "Menu.h"
void initMiniMap(bool loadUpWorld){
int i,x,y;
for(i=0;i<5;++i){
for(x=0;x < 128;++x){
for(y=0;y < 128;++y){
if(!loadUpWorld){ // generate stairs up when making a new world.
switch(map[i][x+y*128]){
case TILE_STAIRS_DOWN:
map[i+1][x+y*128] = TILE_STAIRS_UP;
if(i == 0){
map[i+1][(x+1)+y*128] = TILE_HARDROCK;
map[i+1][x+(y+1)*128] = TILE_HARDROCK;
map[i+1][(x-1)+y*128] = TILE_HARDROCK;
map[i+1][x+(y-1)*128] = TILE_HARDROCK;
map[i+1][(x+1)+(y+1)*128] = TILE_HARDROCK;
map[i+1][(x-1)+(y-1)*128] = TILE_HARDROCK;
map[i+1][(x-1)+(y+1)*128] = TILE_HARDROCK;
map[i+1][(x+1)+(y-1)*128] = TILE_HARDROCK;
} else {
map[i+1][(x+1)+y*128] = TILE_DIRT;
map[i+1][x+(y+1)*128] = TILE_DIRT;
map[i+1][(x-1)+y*128] = TILE_DIRT;
map[i+1][x+(y-1)*128] = TILE_DIRT;
map[i+1][(x+1)+(y+1)*128] = TILE_DIRT;
map[i+1][(x-1)+(y-1)*128] = TILE_DIRT;
map[i+1][(x-1)+(y+1)*128] = TILE_DIRT;
map[i+1][(x+1)+(y-1)*128] = TILE_DIRT;
}
}
}
/* Minimaps */
switch(map[i][x+y*128]){
case TILE_WATER: sf2d_set_pixel (minimap[i], x, y, 0xFFFF0000); break;
case TILE_LAVA: sf2d_set_pixel (minimap[i], x, y, 0xFF0000FF); break;
case TILE_DIRT: sf2d_set_pixel (minimap[i], x, y, 0xFF6C6D82); break;
case TILE_ROCK: sf2d_set_pixel (minimap[i], x, y, 0xFF7F7F7F); break;
case TILE_HARDROCK: sf2d_set_pixel (minimap[i], x, y, 0xFF7F5F5F); break;
case TILE_GRASS: sf2d_set_pixel (minimap[i], x, y, 0xFF00FF00); break;
case TILE_TREE: sf2d_set_pixel (minimap[i], x, y, 0xFF007F00); break;
case TILE_SAND: sf2d_set_pixel (minimap[i], x, y, 0xFF00FFFF); break;
case TILE_CACTUS: sf2d_set_pixel (minimap[i], x, y, 0xFF009F00); break;
case TILE_FLOWER: sf2d_set_pixel (minimap[i], x, y, 0xFF00FF3F); break;
case TILE_IRONORE: sf2d_set_pixel (minimap[i], x, y, 0xFF9696DC); break;
case TILE_GOLDORE: sf2d_set_pixel (minimap[i], x, y, 0xFF9AE8E5); break;
case TILE_GEMORE: sf2d_set_pixel (minimap[i], x, y, 0xFFDE98DF); break;
case TILE_CLOUD: sf2d_set_pixel (minimap[i], x, y, 0xFFFFFFFF); break;
case TILE_CLOUDCACTUS: sf2d_set_pixel (minimap[i], x, y, 0xFFAFAFAF); break;
case TILE_STAIRS_DOWN: sf2d_set_pixel (minimap[i], x, y, 0xFF9F9F9F); break;
case TILE_STAIRS_UP: sf2d_set_pixel (minimap[i], x, y, 0xFF9F9F9F); break;
default: sf2d_set_pixel (minimap[i], x, y, 0xFF111111); break;
}
}
}
}
}
void initNewMap(){
newSeed();
createAndValidateSkyMap(128,128,map[0],data[0]);
createAndValidateTopMap(128,128,map[1],data[1]);
createAndValidateUndergroundMap(128,128,1,map[2],data[2]);
createAndValidateUndergroundMap(128,128,2,map[3],data[3]);
createAndValidateUndergroundMap(128,128,3,map[4],data[4]);
}
void setupGame(bool loadUpWorld){
currentLevel = 1;
// Reset entity manager.
memset(&eManager, 0, sizeof(eManager));
sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF));
if(!loadUpWorld){
initNewMap();
initPlayer();
airWizardHealthDisplay = 2000;
int i;
for(i=0;i<5;++i){
trySpawn(500, i);
}
addEntityToList(newAirWizardEntity(630,820,0), &eManager);
} else {
initPlayer();
loadWorld(currentFileName, &eManager, &player, (u8*)map, (u8*)data);
}
initMiniMap(loadUpWorld);
initGame = 0;
}
int xscr=0, yscr=0;
void tick(){
if(player.p.isDead){
if(player.p.endTimer < 1){
currentMenu = MENU_LOSE;
}
--player.p.endTimer;
return;
} else if(player.p.hasWon){
if(player.p.endTimer < 1){
currentMenu = MENU_WIN;
}
--player.p.endTimer;
return;
}
int i;
for(i = 0;i < 324;++i){
int xx = rand() & 127;
int yy = rand() & 127;
tickTile(xx,yy);
}
tickPlayer();
xscr = player.x - 100;
yscr = player.y - 56;
if (xscr < 16) xscr = 16; else if (xscr > 1832) xscr = 1832;
if (yscr < 16) yscr = 16; else if (yscr > 1912) yscr = 1912;
for(i = 0; i < eManager.lastSlot[currentLevel]; ++i){
Entity * e = &eManager.entities[currentLevel][i];
if((e->type != ENTITY_ZOMBIE && e->type != ENTITY_SLIME) || (e->x > player.x-160 && e->y > player.y-125 && e->x<player.x+160 && e->y<player.y+125)) tickEntity(e);
}
}
void clearScreen(int* data, u8 fill, int size){
int i;
for (i=0; i < size/4; ++i) data[i] = 0x000000FF;
}
char debugText[34];
char bossHealthText[34];
int main()
{
sf2d_init();
csndInit();
noItem = newItem(ITEM_NULL,0);
currentMenu = MENU_TITLE;
currentSelection = 0;
quitGame = false;
icons = sfil_load_PNG_buffer(icons2_png, SF2D_PLACE_RAM);
font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM);
//consoleInit(GFX_BOTTOM, NULL);
// printf("Press 'Start' to exit.\n");
loadSound(&snd_playerHurt, "resources/playerhurt.raw");
loadSound(&snd_playerDeath, "resources/playerdeath.raw");
loadSound(&snd_monsterHurt, "resources/monsterhurt.raw");
loadSound(&snd_test, "resources/test.raw");
loadSound(&snd_pickup, "resources/pickup.raw");
loadSound(&snd_bossdeath, "resources/bossdeath.raw");
loadSound(&snd_craft, "resources/craft.raw");
int i;
for(i = 0;i < 5;++i){
minimap[i] = sf2d_create_texture(128,128,TEXFMT_RGBA8,SF2D_PLACE_RAM);
sf2d_texture_tile32(minimap[i]);
}
sf2d_set_vblank_wait(true);
sf2d_set_clear_color(0xFF);
/* Default inputs */
k_up.input = KEY_DUP | KEY_CPAD_UP | KEY_CSTICK_UP;
k_down.input = KEY_DDOWN | KEY_CPAD_DOWN | KEY_CSTICK_DOWN;
k_left.input = KEY_DLEFT | KEY_CPAD_LEFT | KEY_CSTICK_LEFT;
k_right.input = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT;
k_attack.input = KEY_A | KEY_B | KEY_L | KEY_ZR;
k_menu.input = KEY_X | KEY_Y | KEY_R | KEY_ZL;
k_pause.input = KEY_START;
k_accept.input = KEY_A;
k_decline.input = KEY_B;
k_delete.input = KEY_X;
FILE * file;
/* If btnSave exists, then use that. */
if ((file = fopen("btnSave.bin", "rb"))){
fread(&k_up.input, sizeof(int), 1, file);
fread(&k_down.input, sizeof(int), 1, file);
fread(&k_left.input, sizeof(int), 1, file);
fread(&k_right.input, sizeof(int), 1, file);
fread(&k_attack.input, sizeof(int), 1, file);
fread(&k_menu.input, sizeof(int), 1, file);
fread(&k_pause.input, sizeof(int), 1, file);
fread(&k_accept.input, sizeof(int), 1, file);
fread(&k_decline.input, sizeof(int), 1, file);
fread(&k_delete.input, sizeof(int), 1, file);
fclose(file);
}
//screenShot = false;
tickCount=0;
initRecipes();
defineTables();
while (aptMainLoop()) {
++tickCount;
hidScanInput();
tickKeys(hidKeysHeld(),hidKeysDown());
//if (quitGame || hidKeysHeld() & KEY_SELECT) break;
if (quitGame) break;
//if (hidKeysDown() & (KEY_L | KEY_R)) screenShot = true;
// else screenShot = false;
if(initGame > 0) setupGame(initGame == 1 ? true : false);
if(currentMenu == 0){
tick();
sprintf(fpsstr, " FPS: %.0f, X:%d, Y:%d, E:%d", sf2d_get_fps(),player.x, player.y,eManager.lastSlot[currentLevel]);
sf2d_start_frame(GFX_TOP, GFX_LEFT);
if(currentLevel == 0){
sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5);
sf2d_draw_rectangle(0,0,400,240, 0xDFDFDFAF);
}
offsetX = xscr;offsetY = yscr;
renderBackground(xscr,yscr);
renderEntities(player.x, player.y, &eManager);
renderPlayer();
offsetX = 0;offsetY = 0;
renderItemWithText(player.p.activeItem, 10, 205);
// drawText(debugText,2,208);
drawText(fpsstr,2,225);
sf2d_end_frame();
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
if(currentLevel == 0 && airWizardHealthDisplay > 0){
sprintf(bossHealthText, "BOSS: %.0f%%", ((float)airWizardHealthDisplay/2000.0)*100);
drawText(bossHealthText,2,225);
}
renderGui();
sf2d_draw_texture(minimap[currentLevel], 192, 112);//y:56
sf2d_end_frame();
} else{
tickMenu(currentMenu);
renderMenu(currentMenu,xscr,yscr);
}
sf2d_swapbuffers();
}
freeRecipes();
sf2d_free_texture(icons);
sf2d_free_texture(minimap[0]);
sf2d_free_texture(minimap[1]);
sf2d_free_texture(minimap[2]);
sf2d_free_texture(minimap[3]);
sf2d_free_texture(minimap[4]);
freeSounds();
csndExit();
sf2d_fini();
return 0;
}