* Initial commit

This commit is contained in:
iProgramMC 2023-05-07 18:36:06 +03:00
commit 39513a07b8
10 changed files with 1025 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
keep/*

21
LICENSE.txt Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018-2019 iProgramInCpp
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

140
Makefile Normal file
View File

@ -0,0 +1,140 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
.SECONDARY:
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/ds_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
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := source
DATA :=
INCLUDES := include
GRAPHICS := data
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb -mthumb-interwork
CFLAGS := -g -Wall -O2\
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
-ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM9
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lnds9
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(PNGFILES:.png=.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).ds.gba
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).nds : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.s %.h : %.png %.grit
#---------------------------------------------------------------------------------
grit $< -fts -o$*
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

BIN
OLC_Engine3D_NDS.nds Normal file

Binary file not shown.

BIN
OLC_PlatformGameNDS.nds Normal file

Binary file not shown.

16
README.md Normal file
View File

@ -0,0 +1,16 @@
# DSGameEngine
A DS game engine based off libnds with frame buffer capabilities for the top screen.
It includes basic image drawing functions with transparency and flipping, and basic rectangle drawing.
The graphics work is all done in software, only that the CPU will copy the framebuffer data to the GPU of the Nintendo DS.
It's quite inefficient, but who needs backgrounds and sprites when you can have this?
This repo will also have examples of programs written based off it.
The platform game contains sprites from New Super Mario Bros. for the Nintendo DS. I won't provide them here for legal reasons.
The 3D engine doesn't contain any other things.
You need devkitPro (namely devkitARM) to build.

362
ds_game_engine.h Normal file
View File

@ -0,0 +1,362 @@
#ifndef DS_GAME_ENGINE_INCL
#define DS_GAME_ENGINE_INCL
#define WHITE 0xFFFF
#define BLACK 0x0000
#define SKY 0xEEEF
#define BLUE 0xFC00
#define MAGENTA 0xFC1F
#define CYAN 0xFFE0
#include <nds.h>
/*
int round(float f){
float decpt = f - (int)f;
if(decpt < 0.5f){
return (int)f;
}else{
return (int)f+1;
}
}*/
short screenbuffer_maindisplay[49152];
short screen_width = 256;
short screen_height = 192;
uint32 input_keys = 0;
uint32 input_keysUp = 0;
uint32 input_keysDown = 0;
uint32 input_keysHeld = 0;
touchPosition touch;
PrintConsole bottomScreen;
bool get_key_state(uint32 button){
uint32 s = input_keys & button;
if(s){return true;}else{return false;}
}
bool get_key_down_state(uint32 button){
uint32 s = input_keysDown & button;
if(s){return true;}else{return false;}
}
bool get_key_up_state(uint32 button){
uint32 s = input_keysUp & button;
if(s){return true;}else{return false;}
}
bool get_key_held_state(uint32 button){
uint32 s = input_keysHeld & button;
if(s){return true;}else{return false;}
}
void push_frame(){
dmaCopy(&screenbuffer_maindisplay, BG_GFX, 49152*2);
}
void clear_screenbuffer(short colour){
for(int x = 0; x < 49152; x+=1){
screenbuffer_maindisplay[x] = colour;
}
}
void fill_rectangle(short colour, int w, int h, int dx, int dy){
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = colour;
}
}
}
}
void plot_pixel (int x, int y, short colour){
if((x) >= 0 && (x) < 256 && (y) >= 0 && (y) < 192){
screenbuffer_maindisplay[y*screen_width+x] = colour;
}
}
void draw_line (int x1, int y1, int x2, int y2, short col){
int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i;
dx = x2 - x1; dy = y2 - y1;
dx1 = abs(dx); dy1 = abs(dy);
px = 2 * dy1 - dx1; py = 2 * dx1 - dy1;
if (dy1 <= dx1)
{
if (dx >= 0)
{ x = x1; y = y1; xe = x2; }
else
{ x = x2; y = y2; xe = x1;}
plot_pixel(x, y, col);
for (i = 0; x<xe; i++)
{
x = x + 1;
if (px<0)
px = px + 2 * dy1;
else
{
if ((dx<0 && dy<0) || (dx>0 && dy>0)) y = y + 1; else y = y - 1;
px = px + 2 * (dy1 - dx1);
}
plot_pixel(x, y, col);
}
}
else
{
if (dy >= 0)
{ x = x1; y = y1; ye = y2; }
else
{ x = x2; y = y2; ye = y1; }
plot_pixel(x, y, col);
for (i = 0; y<ye; i++)
{
y = y + 1;
if (py <= 0)
py = py + 2 * dx1;
else
{
if ((dx<0 && dy<0) || (dx>0 && dy>0)) x = x + 1; else x = x - 1;
py = py + 2 * (dx1 - dy1);
}
plot_pixel(x, y, col);
}
}
}
void draw_triangle (int x1, int y1, int x2, int y2, int x3, int y3, short colour){
draw_line (x1, y1, x2, y2, colour);
draw_line (x1, y1, x3, y3, colour);
draw_line (x3, y3, x2, y2, colour);
}
void fill_triangle (int x1, int y1, int x2, int y2, int x3, int y3, short col){
/* Ripped from OneLoneCoder/ConsoleGameEngine */
int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i;
dx = x2 - x1; dy = y2 - y1;
dx1 = abs(dx); dy1 = abs(dy);
px = 2 * dy1 - dx1; py = 2 * dx1 - dy1;
if (dy1 <= dx1)
{
if (dx >= 0)
{ x = x1; y = y1; xe = x2; }
else
{ x = x2; y = y2; xe = x1;}
plot_pixel(x, y, col);
draw_line(x, y, x3, y3, col);
for (i = 0; x<xe; i++)
{
x = x + 1;
if (px<0)
px = px + 2 * dy1;
else
{
if ((dx<0 && dy<0) || (dx>0 && dy>0)) y = y + 1; else y = y - 1;
px = px + 2 * (dy1 - dx1);
}
plot_pixel(x, y, col);
draw_line(x, y, x3, y3, col);
}
}
else
{
if (dy >= 0)
{ x = x1; y = y1; ye = y2; }
else
{ x = x2; y = y2; ye = y1; }
plot_pixel(x, y, col);
draw_line(x, y, x3, y3, col);
for (i = 0; y<ye; i++)
{
y = y + 1;
if (py <= 0)
py = py + 2 * dx1;
else
{
if ((dx<0 && dy<0) || (dx>0 && dy>0)) x = x + 1; else x = x - 1;
py = py + 2 * (dx1 - dy1);
}
plot_pixel(x, y, col);
draw_line(x, y, x3, y3, col);
}
}
}
void draw_image_sizable(short* image, int w, int h, int dx, int dy, int dw, int dh){
/*float pixel_width = dw / w;
float pixel_height= dh / h;
for(int y = 0; y < dh; y++){
for(int x = 0; x < dw; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
int src_y = round(y * pixel_height);
int src_x = round(x * pixel_width);
screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[(src_y*w+src_x)];
}
}
}*/
int w2 = dw, w1 = w, h2 = dh, h1 = h;
// EDIT: added +1 to account for an early rounding problem
int x_ratio = (int)((w1<<16)/w2) +1;
int y_ratio = (int)((h1<<16)/h2) +1;
int x2, y2 ;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x2 = ((j*x_ratio)>>16) ;
y2 = ((i*y_ratio)>>16) ;
if((j+dx) >= 0 && (j+dx) < 256 && (i+dy) >= 0 && (i+dy) < 192){
screenbuffer_maindisplay[(i+dy)*screen_width+(j+dx)] = image[(y2*w1)+x2] ;
}
}
}
}
void draw_image(short* image, int w, int h, int dx, int dy){
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
if(image[y*w+x] == -993){}else{screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[y*w+x];}
}
}
}
}
void draw_image_wsr(short* image, int w, int h, int dx, int dy, int sx, int sy){
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
if(image[(sy+y)*w+(sx+x)] == -993){}else{screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[(sy+y)*w+(sx+x)];}
}
}
}
}
void draw_image_flipped_v(short* image, int w, int h, int dx, int dy){
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
if(image[(h-y-1)*w+x] == -993){}else{screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[(h-y-1)*w+x];}
}
}
}
}
void draw_image_flipped_hv(short* image, int w, int h, int dx, int dy){
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
if(image[(h-y)*w+(w-x-1)] == -993){}else{screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[(h-y)*w+(w-x-1)];}
}
}
}
}
void draw_image_flipped_h(short* image, int w, int h, int dx, int dy){
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
if((x+dx) >= 0 && (x+dx) < 256 && (y+dy) >= 0 && (y+dy) < 192){
if(image[y*w+(w-x-1)] == -993){}else{screenbuffer_maindisplay[(dy+y)*screen_width+(x+dx)] = image[y*w+(w-x-1)];}
}
}
}
}
void OnUserCreate();
void OnUserUpdate();
void make_btm_screen() {consoleSelect(&bottomScreen);}
void printchar(char x, char y, char c) { printf("\x1b[%d;%dH%c", y, x, c); }
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
videoSetMode(MODE_5_2D);
videoSetModeSub(MODE_0_2D);
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG);
bgInit(2, BgType_Bmp16, BgSize_B16_256x256, 0,0);
//consoleInit(&topScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true);
consoleInit(&bottomScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
make_btm_screen();
OnUserCreate();
clear_screenbuffer(0xEEEE);
while(1) {
touchRead(&touch);
scanKeys();
input_keys = keysCurrent();
input_keysUp = keysUp();
input_keysDown = keysDown();
input_keysHeld = keysHeld();
OnUserUpdate();
swiWaitForVBlank();
}
return 0;
}
/*int dx = x2 - x1;
int dy = y2 - y1;
if (dx >= dy){
float y = 0.0f;
if(x1 < x2){
for (int x = x1; x <= x2; x++) {
y = y1 + dy * (x - x1) / dx;
plot_pixel(x, y, colour);
}
}else{
for (int x = x2; x <= x1; x++) {
y = y1 + dy * (x - x1) / dx;
plot_pixel(x, y, colour);
}
}
}else{
float x = 0.0f;
if(dx == 0){
if(y1 < y2){
for (int y = y1; y <= y2; y++) {
plot_pixel(x1, y, colour);
}
}else{
for (int y = y2; y <= y1; y++) {
plot_pixel(x2, y, colour);
}
}
}else{
if(y1 < y2){
for (int y = y1; y <= y2; y++) {
x = x1 + dx * (y - y1) / dy;
plot_pixel(x, y, colour);
}
}else{
for (int y = y2; y <= y1; y++) {
x = x1 + dx * (y - y1) / dy;
plot_pixel(x, y, colour);
}
}
}
}*/
#endif

186
ds_olcEngine3D.cpp Normal file
View File

@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------------
Simple console print demo which prints to bottom screen
and also has a frame buffer for the top screen to which
you can draw stuff
-- iProgramMC - Graphics Engine
-- dovoto - Console bottom screen print
---------------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "block.h"
#include "brick.h"
#include "coin.h"
#include "dirt.h"
#include "door.h"
#include "ground.h"
#include "mariojump.h"
#include "mariostill.h"
#include "question.h"
#include "usedblock.h"
#include <vector>
#include <string>
#include "ds_game_engine.h"
struct vec3d
{
float x, y, z;
};
struct triangle
{
vec3d p[3];
};
struct mesh
{
std::vector<triangle> tris;
};
struct mat4x4
{
float m[4][4] = {0};
};
mesh meshCube;
mat4x4 matProj;
float fTheta;
void MultiplyMatrixVector (vec3d &i, vec3d &o, mat4x4 &m){
o.x = i.x * m.m[0][0] + i.y * m.m[1][0] + i.z * m.m[2][0] + m.m[3][0];
o.y = i.x * m.m[0][1] + i.y * m.m[1][1] + i.z * m.m[2][1] + m.m[3][1];
o.z = i.x * m.m[0][2] + i.y * m.m[1][2] + i.z * m.m[2][2] + m.m[3][2];
float w = i.x * m.m[0][3] + i.y * m.m[1][3] + i.z * m.m[2][3] + m.m[3][3];
if (w != 0.0f)
{
o.x /= w; o.y /= w; o.z /= w;
}
}
int ScreenWidth() {return 256;}
int ScreenHeight(){return 192;}
void OnUserCreate()
{
meshCube.tris = {
// SOUTH
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f },
// EAST
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
{ 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
// NORTH
{ 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f },
// WEST
{ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f },
// TOP
{ 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
{ 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
// BOTTOM
{ 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f },
};
// Projection Matrix
float fNear = 0.1f;
float fFar = 1000.0f;
float fFov = 90.0f;
float fAspectRatio = (float)ScreenHeight() / (float)ScreenWidth();
float fFovRad = 1.0f / tanf(fFov * 0.5f / 180.0f * 3.14159f);
matProj.m[0][0] = fAspectRatio * fFovRad;
matProj.m[1][1] = fFovRad;
matProj.m[2][2] = fFar / (fFar - fNear);
matProj.m[3][2] = (-fFar * fNear) / (fFar - fNear);
matProj.m[2][3] = 1.0f;
matProj.m[3][3] = 0.0f;
//iprintf("\n\n\tGraphics Engine\n\tCoded by iProgramMC\n\tMore modern-like\n\tDo whatever you want!");
}
void OnUserUpdate()
{
clear_screenbuffer(BLACK);
mat4x4 matRotX, matRotZ;
fTheta += 0.01f;
matRotZ.m[0][0] = cosf(fTheta);
matRotZ.m[0][1] = sinf(fTheta);
matRotZ.m[1][0] = -sinf(fTheta);
matRotZ.m[1][1] = cosf(fTheta);
matRotZ.m[2][2] = 1;
matRotZ.m[3][3] = 1;
// Rotation X
matRotX.m[0][0] = 1;
matRotX.m[1][1] = cosf(fTheta * 0.5f);
matRotX.m[1][2] = sinf(fTheta * 0.5f);
matRotX.m[2][1] = -sinf(fTheta * 0.5f);
matRotX.m[2][2] = cosf(fTheta * 0.5f);
matRotX.m[3][3] = 1;
for(auto tri : meshCube.tris){
triangle triProjected, triTranslated, triRotatedZ, triRotatedZX;
// Rotate in Z-Axis
MultiplyMatrixVector(tri.p[0], triRotatedZ.p[0], matRotZ);
MultiplyMatrixVector(tri.p[1], triRotatedZ.p[1], matRotZ);
MultiplyMatrixVector(tri.p[2], triRotatedZ.p[2], matRotZ);
// Rotate in X-Axis
MultiplyMatrixVector(triRotatedZ.p[0], triRotatedZX.p[0], matRotX);
MultiplyMatrixVector(triRotatedZ.p[1], triRotatedZX.p[1], matRotX);
MultiplyMatrixVector(triRotatedZ.p[2], triRotatedZX.p[2], matRotX);
// Offset into the screen
triTranslated = triRotatedZX;
triTranslated.p[0].z = triRotatedZX.p[0].z + 3.0f;
triTranslated.p[1].z = triRotatedZX.p[1].z + 3.0f;
triTranslated.p[2].z = triRotatedZX.p[2].z + 3.0f;
// Project triangles from 3D --> 2D
MultiplyMatrixVector(triTranslated.p[0], triProjected.p[0], matProj);
MultiplyMatrixVector(triTranslated.p[1], triProjected.p[1], matProj);
MultiplyMatrixVector(triTranslated.p[2], triProjected.p[2], matProj);
// Scale into view
triProjected.p[0].x += 1.0f; triProjected.p[0].y += 1.0f;
triProjected.p[1].x += 1.0f; triProjected.p[1].y += 1.0f;
triProjected.p[2].x += 1.0f; triProjected.p[2].y += 1.0f;
triProjected.p[0].x *= 0.5f * (float)ScreenWidth();
triProjected.p[0].y *= 0.5f * (float)ScreenHeight();
triProjected.p[1].x *= 0.5f * (float)ScreenWidth();
triProjected.p[1].y *= 0.5f * (float)ScreenHeight();
triProjected.p[2].x *= 0.5f * (float)ScreenWidth();
triProjected.p[2].y *= 0.5f * (float)ScreenHeight();
// Rasterize triangle
draw_triangle(triProjected.p[0].x, triProjected.p[0].y,
triProjected.p[1].x, triProjected.p[1].y,
triProjected.p[2].x, triProjected.p[2].y, WHITE);
}
push_frame();
}

298
ds_olc_platformer.c Normal file
View File

@ -0,0 +1,298 @@
/*---------------------------------------------------------------------------------
Simple console print demo which prints to bottom screen
and also has a frame buffer for the top screen to which
you can draw stuff
-- iProgramInCpp - Graphics Engine
-- dovoto - Console bottom screen print
---------------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "block.h"
#include "brick.h"
#include "coin.h"
#include "dirt.h"
#include "door.h"
#include "ground.h"
#include "mariojump.h"
#include "mariostill.h"
#include "question.h"
#include "usedblock.h"
#include "ds_game_engine.h"
char sLevel[] = "................................................................"
"................................................................"
".......ooooo...................................................."
"........ooo....................................................."
".......................########................................."
".....BB?BBBB?BB.......###..............#.#......................"
"....................###................#.#......................"
"...................####........................................."
"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.##############.....########"
"...................................#.#...............###........"
"........................############.#............###..........."
"........................#............#.........###.............."
"........................#.############......###................."
"........................#................###...................."
"........................#################......................."
"................................................................";
int nLevelWidth;
int nLevelHeight;
const char TileSize = 8; //8px wide
short block_image[256];
short brick_image[256];
short coin_image[256];
short dirt_image[256];
short door_image[256];
short ground_image[256];
short question_image[256];
short mariojump_image[384];
short mariostill_image[384];
short usedblock_image[256];
bool bPlayerOnGround = false;
int nDirModX = 0, nDirModY = 0;
float fCameraPosX = 0.0f, fCameraPosY = 0.0f;
float fPlayerPosX = 0.0f, fPlayerPosY = 0.0f;
float fPlayerVelX = 0.0f, fPlayerVelY = 0.0f;
unsigned short rng;
short sky_colour = 0xEEEF;
uint32 global_timer = 0;
char ticks = 0;
unsigned short rng_function(unsigned short input){
if(input == 0x560A) input=0;
unsigned short S0 = (unsigned char)input<<8;
S0 = S0 ^ input;
input = ((S0 & 0xFF) << 8) | ((S0 & 0xFF00) >> 8);
S0 = ((unsigned char)S0 << 1) ^ input;
short S1 = (S0 >> 1) ^ 0xFF80;
if((S0 & 1) == 0){
if(S1 == 0xAA55){input = 0;}else{input=S1 ^ 0x1FF4;}
}else{
input = S1 ^ 0x1FF4;
}
return (unsigned short)input;
}
void rng_update() {
rng = rng_function(global_timer);
}
char GetTile(int x, int y){
if(x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight){
return sLevel[y*nLevelWidth+x];
}else{
return ' ';
}
}
void SetTile(char c, int x, int y){
if(x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight){
sLevel[y*nLevelWidth+x] = c;
}
}
void make_btm_screen() {consoleSelect(&bottomScreen);}
void printchar(char x, char y, char c) { printf("\x1b[%d;%dH%c", y, x, c); }
void OnUserCreate()
{
nLevelWidth = 64;
nLevelHeight = 16;
decompress(blockBitmap, &block_image, LZ77);
decompress(brickBitmap, &brick_image, LZ77);
decompress(coinBitmap, &coin_image, LZ77);
decompress(dirtBitmap, &dirt_image, LZ77);
decompress(doorBitmap, &door_image, LZ77);
decompress(groundBitmap, &ground_image, LZ77);
decompress(questionBitmap, &question_image, LZ77);
decompress(usedblockBitmap, &usedblock_image, LZ77);
decompress(mariostillBitmap, &mariostill_image, LZ77);
decompress(mariojumpBitmap, &mariojump_image, LZ77);
iprintf("\n\n\tGraphics Engine\n\tCoded by iProgramInCpp\n\tMore modern-like\n\tDo whatever you want!");
}
void OnUserUpdate()
{
clear_screenbuffer(sky_colour);
//fPlayerVelX = 0.0f;
//fPlayerVelY = 0.0f;
//Handle
if(get_key_state(KEY_UP)){
fPlayerVelY = -6.0f;
}
if(get_key_state(KEY_DOWN)){
fPlayerVelY = 6.0f;
}
if(get_key_state(KEY_LEFT)){
nDirModY = 1;
fPlayerVelX += (bPlayerOnGround ?-6.0f :-4.0f) * 0.01664f;
}
if(get_key_state(KEY_RIGHT)){
nDirModY = 0;
fPlayerVelX += (bPlayerOnGround ? 6.0f : 4.0f) * 0.01664f;
}
if(get_key_down_state(KEY_B)){
if(bPlayerOnGround){
fPlayerVelY = -12.0f;
nDirModX = 1;
}
}
fPlayerVelY += 20.0f * 0.01664f;
if(bPlayerOnGround){
fPlayerVelX += -3.0f * fPlayerVelX * 0.01664f;
if(fabs(fPlayerVelX) < 0.01f){
fPlayerVelX = 0.0f;
}
}
if(fPlayerVelX > 10.0f) fPlayerVelX = 10.0f;
if(fPlayerVelX < -10.0f) fPlayerVelX = -10.0f;
if(fPlayerVelY > 100.0f) fPlayerVelY = 100.0f;
if(fPlayerVelY < -100.0f) fPlayerVelY = -100.0f;
float fNewPlayerPosX = fPlayerPosX + fPlayerVelX * 0.01664f;
float fNewPlayerPosY = fPlayerPosY + fPlayerVelY * 0.01664f;
if(GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f) == 'o')
SetTile('.', fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f);
if(GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f) == 'o')
SetTile('.', fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f);
if(GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f) == 'o')
SetTile('.', fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f);
if(GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f) == 'o')
SetTile('.', fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f);
//Collision
if(fPlayerVelX <= 0){
if(GetTile(fNewPlayerPosX + 0.0f, fPlayerPosY + 0.0f) != '.' ||
GetTile(fNewPlayerPosX + 0.0f, fPlayerPosY + 0.9f) != '.'){
fNewPlayerPosX = (int)fNewPlayerPosX + 1;
fPlayerVelX = 0;
}
}else{
if(GetTile(fNewPlayerPosX + 1.0f, fPlayerPosY + 0.0f) != '.' ||
GetTile(fNewPlayerPosX + 1.0f, fPlayerPosY + 0.9f) != '.'){
fNewPlayerPosX = (int)fNewPlayerPosX;
fPlayerVelX = 0;
}
}
bPlayerOnGround = false;
if(fPlayerVelY <= 0){
if(GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY) != '.' ||
GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY) != '.'){
fNewPlayerPosY = (int)fNewPlayerPosY + 1;
fPlayerVelY = 0;
}
}else{
if(GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY+1) != '.' ||
GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY+1) != '.'){
fNewPlayerPosY = (int)fNewPlayerPosY;
fPlayerVelY = 0;
bPlayerOnGround = true;
nDirModX = 0;
}
}
//nDirModX = !bPlayerOnGround;
fPlayerPosX = fNewPlayerPosX;
fPlayerPosY = fNewPlayerPosY;
fCameraPosX = fPlayerPosX;
fCameraPosY = fPlayerPosY;
//Draw Level
int nTileWidth = 16;
int nTileHeight = 16;
int nVisibleTilesX = SCREEN_WIDTH / nTileWidth;
int nVisibleTilesY = SCREEN_HEIGHT/nTileHeight;
float fOffsetX = fCameraPosX - (float)nVisibleTilesX / 2.0f;
float fOffsetY = fCameraPosY - (float)nVisibleTilesY / 2.0f;
if(fOffsetX <= 0.0f) fOffsetX = 0.0f;
if(fOffsetY <= 0.0f) fOffsetY = 0.0f;
if(fOffsetX > (float)(nLevelWidth - nVisibleTilesX)) fOffsetX = nLevelWidth - nVisibleTilesX;
if(fOffsetY > (float)(nLevelHeight- nVisibleTilesY)) fOffsetY = nLevelHeight- nVisibleTilesY;
float fTileOffsetX = (fOffsetX - (int)fOffsetX) * nTileWidth;
float fTileOffsetY = (fOffsetY - (int)fOffsetY) * nTileHeight;
for(int x = -1; x < nVisibleTilesX+1; x++){
for(int y = -1; y < nVisibleTilesY+1; y++){
char sTileID = GetTile(x + fOffsetX, y+fOffsetY);
switch(sTileID){
case '.':
break;
case '#':
draw_image(block_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case 'o':
draw_image(coin_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case '?':
draw_image(question_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case 'B':
draw_image(brick_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case 'G':
draw_image(ground_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case 'D':
draw_image(dirt_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case 'E':
draw_image(door_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
case 'U':
draw_image(usedblock_image, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
default:
fill_rectangle(0x0000, nTileWidth, nTileHeight, x*nTileWidth-fTileOffsetX,y*nTileHeight-fTileOffsetY);
break;
}
}
}
if(nDirModX){
if(nDirModY){
draw_image_flipped_h(mariojump_image, nTileWidth, 24, (fPlayerPosX - fOffsetX)*nTileWidth, (fPlayerPosY - fOffsetY)*nTileHeight-8);
}else{
draw_image(mariojump_image, nTileWidth, 24, (fPlayerPosX - fOffsetX)*nTileWidth, (fPlayerPosY - fOffsetY)*nTileHeight-8);
}
}else{
if(nDirModY){
draw_image_flipped_h(mariostill_image, nTileWidth, 24, (fPlayerPosX - fOffsetX)*nTileWidth, (fPlayerPosY - fOffsetY)*nTileHeight-8);
}else{
draw_image(mariostill_image, nTileWidth, 24, (fPlayerPosX - fOffsetX)*nTileWidth, (fPlayerPosY - fOffsetY)*nTileHeight-8);
}
}
push_frame();
}

1
keep Submodule

@ -0,0 +1 @@
Subproject commit 1295f24e03d12a8bf80394ab5933f727ca22097c