merge: merge changes from upstream master
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@ IRXEMBEDDEDEXT := irx-em
|
||||
CFLAGS += -D_EE -Wall -O3
|
||||
LINKFLAGS += -O3 -Wl,-zmax-page-size=128
|
||||
ASFLAGS += -O3
|
||||
LIB += -lstdc++ -ldma -lpacket2 -lgraph -ldraw -lmath3d -lpng -lz -lpad -laudsrv -lpatches -lcdvd
|
||||
LIB += -lstdc++ -ldma -lpacket2 -lgraph -ldraw -lmath3d -lpng -ldebug -lz -lpad -laudsrv -lpatches -lcdvd
|
||||
INC += -I$(PS2DEV)/ps2sdk/ee/include -I$(PS2DEV)/ps2sdk/common/include -I$(PS2DEV)/ps2sdk/ports/include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
@@ -121,6 +121,7 @@ List of games developed with Tyra.
|
||||
If you created one, please contact me - I will add it to the list :)
|
||||
|
||||
* [Tyracraft](https://github.com/Wellinator/tyracraft) by [Wellinator](https://github.com/Wellinator)
|
||||
* [Game with car](https://github.com/freebytego/gwc-ps2) by [freebytego](https://github.com/freebytego)
|
||||
* [Rock, paper, scissors](https://github.com/GuidoDQR/my-ps2-game) by [GuidoDQR](https://github.com/GuidoDQR)
|
||||
* [TyraTale](https://github.com/Br4k2n/TyraTale) by [Br4k2n](https://github.com/Br4k2n)
|
||||
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
docker pull h4570/tyra
|
||||
git clone https://github.com/h4570/tyra.git
|
||||
```
|
||||
3. Open `VSCode` and open previously cloned directory.
|
||||
4. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/`
|
||||
5. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2.
|
||||
6. Click `CTRL+SHIFT+P`, type `Tasks: Run task` and run `Start docker container` - Repeat this step every time you want to start working with Tyra (every reboot)
|
||||
7. Click `CTRL+SHIFT+P`, type `Tasks: Run build task`
|
||||
8. Tyra should automatically compile engine, `demo` game and run `PCSX2`. If you want to compile & run tutorials, please change `buildDirectory` in `settings.json` to example `tutorials/01-hello`
|
||||
3. Download the [assets.zip](https://github.com/h4570/tyra/releases) file and unzip it into the tyra directory
|
||||
4. Open `VSCode` and open previously cloned directory.
|
||||
5. In `VSCode` open `.vscode/configurations/windows-docker` and copy configuration files into `.vscode/`
|
||||
6. In `c_cpp_properties.json` fix all `YOUR-INTELLISENSE-PATH` with path from point 2.
|
||||
7. Click `CTRL+SHIFT+P`, type `Tasks: Run task` and run `Start docker container` - Repeat this step every time you want to start working with Tyra (every reboot)
|
||||
8. Click `CTRL+SHIFT+P`, type `Tasks: Run build task`
|
||||
9. Tyra should automatically compile engine, `demo` game and run `PCSX2`. If you want to compile & run tutorials, please change `buildDirectory` in `settings.json` to example `tutorials/01-hello`
|
||||
|
||||
+23
-14
@@ -20,6 +20,7 @@
|
||||
#else // IF Debug
|
||||
|
||||
#include <stdio.h>
|
||||
#include <debug.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
@@ -48,9 +49,7 @@ class TyraDebug {
|
||||
(void)expander{0, (void(ss << std::forward<Args>(args)), 0)...};
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logFile = getLogFile();
|
||||
*logFile << ss.str();
|
||||
logFile->flush();
|
||||
writeInLogFile(&ss);
|
||||
} else {
|
||||
printf("%s", ss.str().c_str());
|
||||
}
|
||||
@@ -65,9 +64,7 @@ class TyraDebug {
|
||||
ss1 << "|\n";
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logFile = getLogFile();
|
||||
*logFile << ss1.str();
|
||||
logFile->flush();
|
||||
writeInLogFile(&ss1);
|
||||
} else {
|
||||
printf("%s", ss1.str().c_str());
|
||||
}
|
||||
@@ -80,20 +77,22 @@ class TyraDebug {
|
||||
ss2 << "====================================\n\n";
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logFile = getLogFile();
|
||||
*logFile << ss2.str();
|
||||
logFile->flush();
|
||||
writeInLogFile(&ss2);
|
||||
} else {
|
||||
printf("%s", ss2.str().c_str());
|
||||
}
|
||||
|
||||
init_scr();
|
||||
for (;;) {
|
||||
scr_setXY(20, 10);
|
||||
scr_printf(ss1.str().c_str());
|
||||
writeAssertLinesInScreen(args...);
|
||||
scr_printf(ss2.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<std::ofstream> logFile;
|
||||
static std::ofstream* getLogFile();
|
||||
static void writeInLogFile(std::stringstream* ss);
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
static void writeAssertLines(Arg&& arg, Args&&... args) {
|
||||
@@ -105,13 +104,23 @@ class TyraDebug {
|
||||
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
|
||||
|
||||
if (Tyra::Info::writeLogsToFile) {
|
||||
auto* logfile = getLogFile();
|
||||
*logfile << ss.str();
|
||||
logFile->flush();
|
||||
writeInLogFile(&ss);
|
||||
} else {
|
||||
printf("%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Arg, typename... Args>
|
||||
static void writeAssertLinesInScreen(Arg&& arg, Args&&... args) {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "| " << std::forward<Arg>(arg) << "\n";
|
||||
using expander = int[];
|
||||
(void)expander{
|
||||
0, (void(ss << "| " << std::forward<Args>(args) << "\n"), 0)...};
|
||||
|
||||
scr_printf(ss.str().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NDEBUG
|
||||
@@ -21,7 +21,7 @@ class Version {
|
||||
~Version() {}
|
||||
|
||||
static const u8 major = 2;
|
||||
static const u8 minor = 1;
|
||||
static const u8 minor = 2;
|
||||
static const u8 patch = 0;
|
||||
|
||||
static std::string toString() {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "debug/debug.hpp"
|
||||
#include "renderer/core/2d/sprite/sprite.hpp"
|
||||
#include "renderer/core/texture/renderer_core_texture_buffers.hpp"
|
||||
#include "renderer/3d/pipeline/shared/pipeline_texture_mapping_type.hpp"
|
||||
#include "renderer/core/texture/models/texture.hpp"
|
||||
#include "renderer/renderer_settings.hpp"
|
||||
#include <packet2_utils.h>
|
||||
@@ -30,6 +31,9 @@ class RendererCore2D {
|
||||
void render(const Sprite& sprite,
|
||||
const RendererCoreTextureBuffers& texBuffers, Texture* texture);
|
||||
|
||||
void setTextureMappingType(
|
||||
const PipelineTextureMappingType textureMappingType);
|
||||
|
||||
private:
|
||||
void setPrim();
|
||||
void setLod();
|
||||
|
||||
@@ -24,7 +24,7 @@ class Sprite {
|
||||
~Sprite();
|
||||
|
||||
u32 id;
|
||||
Vec2 position, size;
|
||||
Vec2 position, size, offset;
|
||||
float scale;
|
||||
Color color;
|
||||
SpriteMode mode;
|
||||
|
||||
@@ -10,16 +10,11 @@
|
||||
|
||||
#include "debug/debug.hpp"
|
||||
|
||||
std::unique_ptr<std::ofstream> TyraDebug::logFile;
|
||||
|
||||
std::ofstream* TyraDebug::getLogFile() {
|
||||
if (logFile) {
|
||||
return logFile.get();
|
||||
} else {
|
||||
logFile = std::make_unique<std::ofstream>();
|
||||
logFile->open(Tyra::FileUtils::fromCwd("log.txt"),
|
||||
std::ofstream::out | std::ofstream::app);
|
||||
return logFile.get();
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
void TyraDebug::writeInLogFile(std::stringstream* ss) {
|
||||
std::ofstream logFile;
|
||||
logFile.open(Tyra::FileUtils::fromCwd("log.txt"),
|
||||
std::ofstream::out | std::ofstream::app);
|
||||
logFile << ss->str();
|
||||
logFile.flush();
|
||||
// logFile.close();
|
||||
}
|
||||
|
||||
@@ -20,36 +20,20 @@
|
||||
#include "file/file_utils.hpp"
|
||||
|
||||
// external IRX modules
|
||||
#define EXTERN_IRX(_irx) \
|
||||
extern u8 _irx[]; \
|
||||
extern int size_##_irx
|
||||
|
||||
extern u8 sio2man_irx[];
|
||||
extern int size_sio2man_irx;
|
||||
|
||||
extern u8 padman_irx[];
|
||||
extern int size_padman_irx;
|
||||
|
||||
extern u8 audsrv_irx[];
|
||||
extern int size_audsrv_irx;
|
||||
|
||||
extern u8 libsd_irx[];
|
||||
extern int size_libsd_irx;
|
||||
|
||||
extern u8 fileXio_irx[];
|
||||
extern int size_fileXio_irx;
|
||||
|
||||
extern u8 iomanX_irx[];
|
||||
extern int size_iomanX_irx;
|
||||
|
||||
extern u8 bdm_irx[];
|
||||
extern int size_bdm_irx;
|
||||
|
||||
extern u8 bdmfs_fatfs_irx[];
|
||||
extern int size_bdmfs_fatfs_irx;
|
||||
|
||||
extern u8 usbd_irx[];
|
||||
extern int size_usbd_irx;
|
||||
|
||||
extern u8 usbmass_bd_irx[];
|
||||
extern int size_usbmass_bd_irx;
|
||||
EXTERN_IRX(sio2man_irx);
|
||||
EXTERN_IRX(padman_irx);
|
||||
EXTERN_IRX(audsrv_irx);
|
||||
EXTERN_IRX(libsd_irx);
|
||||
EXTERN_IRX(fileXio_irx);
|
||||
EXTERN_IRX(iomanX_irx);
|
||||
EXTERN_IRX(bdm_irx);
|
||||
EXTERN_IRX(bdmfs_fatfs_irx);
|
||||
EXTERN_IRX(usbd_irx);
|
||||
EXTERN_IRX(usbmass_bd_irx);
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
|
||||
@@ -84,10 +84,12 @@ void RendererCore2D::render(const Sprite& sprite,
|
||||
else if (sizeY > sizeX)
|
||||
texS = texMax / (sizeY / sizeX);
|
||||
|
||||
rect->t0.s = sprite.flipHorizontal ? texS : 0.0F;
|
||||
rect->t0.t = sprite.flipVertical ? texT : 0.0F;
|
||||
rect->t1.s = sprite.flipHorizontal ? 0.0F : texS;
|
||||
rect->t1.t = sprite.flipVertical ? 0.0F : texT;
|
||||
rect->t0.s =
|
||||
sprite.flipHorizontal ? (texS + sprite.offset.x) : sprite.offset.x;
|
||||
rect->t0.t = sprite.flipVertical ? (texT + sprite.offset.y) : sprite.offset.y;
|
||||
rect->t1.s =
|
||||
sprite.flipHorizontal ? sprite.offset.x : (texS + sprite.offset.x);
|
||||
rect->t1.t = sprite.flipVertical ? sprite.offset.y : (texT + sprite.offset.y);
|
||||
|
||||
rect->color.r = sprite.color.r;
|
||||
rect->color.g = sprite.color.g;
|
||||
@@ -131,4 +133,10 @@ void RendererCore2D::render(const Sprite& sprite,
|
||||
context = !context;
|
||||
}
|
||||
|
||||
void RendererCore2D::setTextureMappingType(
|
||||
const PipelineTextureMappingType textureMappingType) {
|
||||
lod.mag_filter = textureMappingType;
|
||||
lod.min_filter = textureMappingType;
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -18,6 +18,7 @@ Sprite::Sprite() {
|
||||
flipVertical = false;
|
||||
size.set(32.0F, 32.0F);
|
||||
position.set(100.0F, 100.0F);
|
||||
offset.set(0.0F, 0.0F);
|
||||
scale = 1.0F;
|
||||
mode = MODE_REPEAT;
|
||||
setDefaultColor();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
TARGET := tutorial_10.elf
|
||||
ENGINEDIR := ../../engine
|
||||
|
||||
#The Directories, Source, Includes, Objects, Binary and Resources
|
||||
SRCDIR := src
|
||||
INCDIR := inc
|
||||
BUILDDIR := obj
|
||||
TARGETDIR := bin
|
||||
RESDIR := res
|
||||
SRCEXT := cpp
|
||||
VSMEXT := vsm
|
||||
VCLEXT := vcl
|
||||
VCLPPEXT := vclpp
|
||||
DEPEXT := d
|
||||
OBJEXT := o
|
||||
|
||||
#Flags, Libraries and Includes
|
||||
CFLAGS :=
|
||||
LIB :=
|
||||
LIBDIRS :=
|
||||
INC := -I$(INCDIR)
|
||||
INCDEP := -I$(INCDIR)
|
||||
|
||||
include ../Makefile.tutorials-base
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2023, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Guido Diego Quispe Robles
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
|
||||
#define FONT_CHAR_SIZE 96
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Font {
|
||||
public:
|
||||
Font();
|
||||
void load(TextureRepository& repository, Renderer2D* renderer);
|
||||
void free(TextureRepository& repository);
|
||||
void drawText(const char* text, const int& x, const int& y, Color color);
|
||||
void drawText(const std::string& text, const int& x, const int& y,
|
||||
Color color);
|
||||
|
||||
private:
|
||||
const static int chars[FONT_CHAR_SIZE];
|
||||
const static int charWidths[FONT_CHAR_SIZE];
|
||||
|
||||
Renderer2D* renderer2D;
|
||||
Sprite allFont;
|
||||
std::array<Sprite, FONT_CHAR_SIZE> font;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2023, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Guido Diego Quispe Robles
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tyra>
|
||||
#include "font_sprite.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Tutorial10 : public Game {
|
||||
public:
|
||||
explicit Tutorial10(Engine* engine);
|
||||
~Tutorial10();
|
||||
|
||||
void init();
|
||||
void loop();
|
||||
|
||||
private:
|
||||
void loadTexture();
|
||||
void loadSprite();
|
||||
void handlePad();
|
||||
|
||||
int padTimer;
|
||||
Engine* engine;
|
||||
Pad* pad;
|
||||
Font font;
|
||||
|
||||
Sprite sprite;
|
||||
Sprite spriteFlip;
|
||||
Sprite spriteScale;
|
||||
Sprite spriteStretch;
|
||||
std::string strFilter;
|
||||
|
||||
PipelineTextureMappingType textureFilter;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
@@ -0,0 +1,4 @@
|
||||
$ConfigFile = Join-Path $PSScriptRoot '../../windows-pcsx2.ps1'
|
||||
. $ConfigFile
|
||||
|
||||
RunPCSX2
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2023, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Guido Diego Quispe Robles
|
||||
*/
|
||||
|
||||
#include "font_sprite.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
const int Font::chars[FONT_CHAR_SIZE]{
|
||||
' ', '!', '"', ' ', '$', '%', ' ', '{', '(', ')', ' ', '+', ',', '-',
|
||||
'.', '/', '0', '1', '2', '3', '4', '5', '6', '2', '8', '9', ':', ';',
|
||||
'<', '=', '>', '?', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
||||
'X', 'Y', 'Z', ' ', ' ', ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e',
|
||||
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
|
||||
't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '}', ']', '~', ' '};
|
||||
|
||||
const int Font::charWidths[FONT_CHAR_SIZE]{
|
||||
0, 1, 3, 0, 5, 9, 0, 9, 3, 3, 0, 5, 2, 2, 1, 4, 4, 2, 4, 4, 5, 4, 4, 4,
|
||||
4, 4, 1, 2, 4, 5, 4, 4, 0, 6, 5, 5, 5, 4, 4, 5, 5, 1, 4, 5, 4, 7, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 6, 7, 5, 5, 4, 0, 0, 0, 0, 0, 0, 5, 4, 4, 4, 4, 3, 4,
|
||||
4, 1, 2, 4, 1, 7, 4, 4, 4, 4, 3, 4, 3, 4, 5, 7, 4, 4, 4, 2, 5, 2, 6, 0,
|
||||
};
|
||||
|
||||
Font::Font() {}
|
||||
|
||||
void Font::load(TextureRepository& repository, Renderer2D* renderer) {
|
||||
renderer2D = renderer;
|
||||
|
||||
float height = 16.0F;
|
||||
float width = 16.0F;
|
||||
|
||||
allFont.mode = MODE_REPEAT;
|
||||
allFont.size = Vec2(255, 127);
|
||||
|
||||
auto filepath = FileUtils::fromCwd("earthbound-Font.png");
|
||||
auto* texture = repository.add(filepath);
|
||||
texture->addLink(allFont.id);
|
||||
|
||||
int column = 0;
|
||||
int arrow = 0;
|
||||
|
||||
for (int i = 0; i < FONT_CHAR_SIZE; i++) {
|
||||
font[i].id = allFont.id;
|
||||
font[i].mode = MODE_REPEAT;
|
||||
font[i].size = Vec2(width, height);
|
||||
font[i].offset = Vec2(width * column, height * arrow);
|
||||
column++;
|
||||
|
||||
if (column == 16) {
|
||||
arrow++;
|
||||
column = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Font::free(TextureRepository& repository) {
|
||||
repository.freeBySprite(allFont);
|
||||
for (int i = 0; i < FONT_CHAR_SIZE; i++) {
|
||||
repository.freeBySprite(font[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Font::drawText(const char* text, const int& x, const int& y, Color color) {
|
||||
drawText(std::string(text), x, y, color);
|
||||
}
|
||||
|
||||
void Font::drawText(const std::string& text, const int& x, const int& y,
|
||||
Color color) {
|
||||
int sizeText = text.size();
|
||||
|
||||
int offsetY = 0;
|
||||
int offsetX = 0;
|
||||
|
||||
for (int i = 0; i < sizeText; i++) {
|
||||
int fontPos = text[i];
|
||||
Sprite fontSpr = font[0];
|
||||
|
||||
for (int j = 0; j < FONT_CHAR_SIZE; j++) {
|
||||
if (fontPos == chars[j]) {
|
||||
fontPos = j;
|
||||
fontSpr = font[j];
|
||||
fontSpr.color = color;
|
||||
fontSpr.position = Vec2(x + offsetX, y + offsetY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fontPos == '\n') {
|
||||
offsetY += 18;
|
||||
offsetX = 0.0f;
|
||||
} else {
|
||||
if ((fontPos != ' ') && (fontPos != '\t')) {
|
||||
renderer2D->render(fontSpr);
|
||||
offsetX += charWidths[fontPos] + 2;
|
||||
} else {
|
||||
offsetX += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2023, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Guido Diego Quispe Robles
|
||||
*/
|
||||
|
||||
#include "engine.hpp"
|
||||
#include "tutorial_10.hpp"
|
||||
|
||||
/**
|
||||
* In this tutorial we will learn:
|
||||
* - How works the offset of the sprite
|
||||
* - How works the texture mapping
|
||||
* - How to write text (font)
|
||||
*/
|
||||
|
||||
int main() {
|
||||
Tyra::Engine engine;
|
||||
Tyra::Tutorial10 game(&engine);
|
||||
engine.run(&game);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022-2023, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Guido Diego Quispe Robles
|
||||
*/
|
||||
|
||||
#include <tyra>
|
||||
#include "tutorial_10.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
Tutorial10::Tutorial10(Engine* t_engine)
|
||||
: padTimer(0), engine(t_engine), pad(&t_engine->pad) {}
|
||||
|
||||
Tutorial10::~Tutorial10() {
|
||||
engine->renderer.getTextureRepository().freeBySprite(sprite);
|
||||
engine->renderer.getTextureRepository().freeBySprite(spriteFlip);
|
||||
engine->renderer.getTextureRepository().freeBySprite(spriteScale);
|
||||
engine->renderer.getTextureRepository().freeBySprite(spriteStretch);
|
||||
font.free(engine->renderer.getTextureRepository());
|
||||
}
|
||||
|
||||
void Tutorial10::init() {
|
||||
engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F));
|
||||
|
||||
/** Load all the sprites of the sprite sheet. */
|
||||
font.load(engine->renderer.getTextureRepository(),
|
||||
&engine->renderer.renderer2D);
|
||||
|
||||
/** Sprite contains rectangle information. */
|
||||
loadSprite();
|
||||
|
||||
/** Texture contains png image. */
|
||||
loadTexture();
|
||||
|
||||
/** Set the texture filtering. */
|
||||
textureFilter = TyraNearest;
|
||||
|
||||
engine->renderer.core.renderer2D.setTextureMappingType(textureFilter);
|
||||
}
|
||||
|
||||
void Tutorial10::loop() {
|
||||
auto& renderer = engine->renderer;
|
||||
|
||||
/** Change the texture filtering of the texture.
|
||||
*
|
||||
* The options are:
|
||||
* TyraNearest (Point Sampling):
|
||||
* uses the color of the texel closest to the pixel center for the pixel
|
||||
* color.
|
||||
*
|
||||
* TyraLinear (Bilinear Sampling):
|
||||
* the four nearest texels to the pixel center are sampled
|
||||
* and their colors are combined by weighted average according to distance.
|
||||
*
|
||||
* By default it is linear.
|
||||
*/
|
||||
|
||||
renderer.core.renderer2D.setTextureMappingType(textureFilter);
|
||||
|
||||
handlePad();
|
||||
|
||||
/** Begin frame will clear our screen. */
|
||||
renderer.beginFrame();
|
||||
|
||||
/** Render sprite. */
|
||||
renderer.renderer2D.render(sprite);
|
||||
renderer.core.renderer2D.setTextureMappingType(TyraLinear);
|
||||
renderer.renderer2D.render(spriteFlip);
|
||||
renderer.core.renderer2D.setTextureMappingType(textureFilter);
|
||||
renderer.renderer2D.render(spriteScale);
|
||||
renderer.renderer2D.render(spriteStretch);
|
||||
|
||||
font.drawText("tests with sprite sheet", (512 / 2) - 60, 10,
|
||||
Color(255, 255, 255));
|
||||
font.drawText("Press Cross for nearest filter", (512 / 2) - 70, 50,
|
||||
Color(255, 255, 255));
|
||||
font.drawText("Press Circle for linear filter", (512 / 2) - 65, 70,
|
||||
Color(255, 255, 255));
|
||||
font.drawText("Use left stick for move the offsets of the sprites",
|
||||
(512 / 2) - 110, 90, Color(255, 255, 255));
|
||||
font.drawText("sprite 32x32\n scaled x3", sprite.position.x + 16,
|
||||
sprite.position.y - 40, Color(255, 255, 255));
|
||||
font.drawText("sprite 32x32\nscaled x3 with flip", spriteFlip.position.x + 4,
|
||||
spriteFlip.position.y - 40, Color(255, 255, 255));
|
||||
font.drawText("sprite 96x96 with\n repeat mode", spriteScale.position.x + 6,
|
||||
spriteScale.position.y - 40, Color(255, 255, 255));
|
||||
font.drawText("sprite 96x96 with\n stretch mode",
|
||||
spriteStretch.position.x + 6, spriteStretch.position.y - 40,
|
||||
Color(255, 255, 255));
|
||||
|
||||
if (textureFilter == TyraLinear) {
|
||||
strFilter = "Filter: Linear";
|
||||
} else {
|
||||
strFilter = "Filter: Nearest";
|
||||
}
|
||||
|
||||
int posX1 = sprite.position.x + 16;
|
||||
int posX2 = spriteFlip.position.x + 16;
|
||||
int posX3 = spriteStretch.position.x + 16;
|
||||
int posX4 = spriteScale.position.x + 16;
|
||||
|
||||
int posY1 = sprite.position.y + (sprite.size.y * sprite.scale) + 16;
|
||||
int posY2 =
|
||||
spriteFlip.position.y + (spriteFlip.size.y * spriteFlip.scale) + 16;
|
||||
int posY3 = spriteStretch.position.y +
|
||||
(spriteStretch.size.y * spriteStretch.scale) + 16;
|
||||
int posY4 =
|
||||
spriteScale.position.y + (spriteScale.size.y * spriteScale.scale) + 16;
|
||||
|
||||
font.drawText(strFilter, posX1, posY1, Color(255, 255, 255));
|
||||
font.drawText("Filter: Linear", posX2, posY2, Color(255, 255, 255));
|
||||
font.drawText(strFilter, posX3, posY3, Color(255, 255, 255));
|
||||
font.drawText(strFilter, posX4, posY4, Color(255, 255, 255));
|
||||
|
||||
/** End frame will perform vsync. */
|
||||
renderer.endFrame();
|
||||
}
|
||||
|
||||
void Tutorial10::handlePad() {
|
||||
if (engine->pad.getClicked().Cross) {
|
||||
textureFilter = TyraNearest;
|
||||
} else if (engine->pad.getClicked().Circle) {
|
||||
textureFilter = TyraLinear;
|
||||
}
|
||||
|
||||
/** Move the offset of the sprites.
|
||||
*
|
||||
* The offset of the sprite need to be equal or greater to zero
|
||||
* or a graphical error occurs.
|
||||
*
|
||||
* And the sum of the sprite size and the offset must be less than 1024
|
||||
* or a graphical error occurs.
|
||||
*
|
||||
* Sum with repeat mode:
|
||||
* Max = sprite.size + sprite.offset.
|
||||
*
|
||||
* Sum with strecth mode:
|
||||
* Max = original size of the image + sprite.offset.
|
||||
*
|
||||
* If it continues moving past these values
|
||||
* in a moment it will return to normal but
|
||||
* the error will be repeated with another value.
|
||||
*/
|
||||
|
||||
if (padTimer <= 0) {
|
||||
if (pad->getLeftJoyPad().v <= 100) { // up
|
||||
sprite.offset -= Vec2(0, 16);
|
||||
spriteFlip.offset -= Vec2(0, 16);
|
||||
spriteScale.offset -= Vec2(0, 16);
|
||||
spriteStretch.offset -= Vec2(0, 16);
|
||||
padTimer = 20;
|
||||
printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y);
|
||||
} else if (pad->getLeftJoyPad().v >= 200) { // down
|
||||
sprite.offset += Vec2(0, 16);
|
||||
spriteFlip.offset += Vec2(0, 16);
|
||||
spriteScale.offset += Vec2(0, 16);
|
||||
spriteStretch.offset += Vec2(0, 16);
|
||||
padTimer = 20;
|
||||
printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y);
|
||||
}
|
||||
|
||||
if (pad->getLeftJoyPad().h <= 100) { // left
|
||||
sprite.offset -= Vec2(16, 0);
|
||||
spriteFlip.offset -= Vec2(16, 0);
|
||||
spriteScale.offset -= Vec2(16, 0);
|
||||
spriteStretch.offset -= Vec2(16, 0);
|
||||
padTimer = 20;
|
||||
printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y);
|
||||
} else if (pad->getLeftJoyPad().h >= 200) { // right
|
||||
sprite.offset += Vec2(16, 0);
|
||||
spriteFlip.offset += Vec2(16, 0);
|
||||
spriteScale.offset += Vec2(16, 0);
|
||||
spriteStretch.offset += Vec2(16, 0);
|
||||
padTimer = 20;
|
||||
printf("New offset: %f,%f\n", sprite.offset.x, sprite.offset.y);
|
||||
}
|
||||
|
||||
} else {
|
||||
padTimer--;
|
||||
}
|
||||
}
|
||||
|
||||
void Tutorial10::loadSprite() {
|
||||
const auto& screenSettings = engine->renderer.core.getSettings();
|
||||
|
||||
int offset = 25;
|
||||
|
||||
sprite.mode = SpriteMode::MODE_REPEAT;
|
||||
|
||||
/** Let's scale it down */
|
||||
sprite.size = Vec2(32.0F, 32.0F);
|
||||
sprite.scale = 3;
|
||||
|
||||
/** Set the position */
|
||||
sprite.position =
|
||||
Vec2(offset, screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F);
|
||||
|
||||
spriteFlip.mode = SpriteMode::MODE_REPEAT;
|
||||
|
||||
spriteFlip.flipHorizontal = true;
|
||||
spriteFlip.flipVertical = true;
|
||||
|
||||
spriteFlip.size = Vec2(32.0F, 32.0F);
|
||||
|
||||
spriteFlip.scale = 3;
|
||||
|
||||
spriteFlip.position =
|
||||
Vec2(((offset * 2) + (32.0F * 3)),
|
||||
screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F);
|
||||
|
||||
spriteScale.mode = SpriteMode::MODE_REPEAT;
|
||||
|
||||
spriteScale.size = Vec2(96.0F, 96.0F);
|
||||
|
||||
spriteScale.position =
|
||||
Vec2(((offset * 3) + ((32.0F * 3) * 2)),
|
||||
screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F);
|
||||
|
||||
spriteStretch.mode = SpriteMode::MODE_STRETCH;
|
||||
|
||||
spriteStretch.size = Vec2(96.0F, 96.0F);
|
||||
|
||||
spriteStretch.position =
|
||||
Vec2(((offset * 4) + ((32.0F * 3) * 3)),
|
||||
screenSettings.getHeight() / 2.0F - sprite.size.y / 2.0F);
|
||||
|
||||
TYRA_LOG("Sprite created!");
|
||||
}
|
||||
|
||||
void Tutorial10::loadTexture() {
|
||||
/**
|
||||
* Renderer has high layer functions,
|
||||
* which allows to render:
|
||||
* - Sprite (2D)
|
||||
* - Mesh (3D)
|
||||
*
|
||||
* It uses ONLY low layer functions which are in renderer.core
|
||||
*/
|
||||
auto& renderer = engine->renderer;
|
||||
|
||||
/**
|
||||
* TextureRepository is a repository of textures.
|
||||
* It is a singleton class, with all game textures.
|
||||
* We are linking these textures with sprite's (2D) and mesh (3D) materials.
|
||||
*/
|
||||
auto& textureRepository = renderer.getTextureRepository();
|
||||
|
||||
/**
|
||||
* Texture is stored in "res" directory.
|
||||
* Content of "res" directory is automatically copied into
|
||||
* "bin" directory, which contains our final game.
|
||||
*
|
||||
* File utils automatically add's device prefix to the path,
|
||||
* based on current working directory.
|
||||
*
|
||||
* In PS2 world:
|
||||
* - USB has a "mass:" prefix
|
||||
* - Our PC in PS2Link has a "host:" prefix
|
||||
* - Our PC in PCSX2 has a "host:" prefix
|
||||
*/
|
||||
auto filepath = FileUtils::fromCwd("atlas.png");
|
||||
|
||||
/**
|
||||
* Tyra supports following PNG formats:
|
||||
* 32bpp (RGBA)
|
||||
* 24bpp (RGB)
|
||||
* 8bpp, palletized (RGBA)
|
||||
* 4bpp, palletized (RGBA)
|
||||
*
|
||||
* 8bpp and 4bpp are the fastest.
|
||||
* All of these formats can be easily exported via GIMP.
|
||||
*/
|
||||
auto* texture = textureRepository.add(filepath);
|
||||
|
||||
/** Let's assign this texture to sprite. */
|
||||
texture->addLink(sprite.id);
|
||||
|
||||
spriteFlip.id = sprite.id;
|
||||
spriteScale.id = sprite.id;
|
||||
spriteStretch.id = sprite.id;
|
||||
|
||||
TYRA_LOG("Texture loaded!");
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
Reference in New Issue
Block a user