From 35465f27ed87646a18cd9298eae861f14385300e Mon Sep 17 00:00:00 2001
From: Ekaitz Zarraga <ekaitz@elenq.tech>
Date: Thu, 23 Dec 2021 20:52:49 +0100
Subject: First commit: moves a simple thing on the screen

---
 .gitignore       |   2 +
 Makefile         |  25 +++++++++++
 manifest.scm     |   1 +
 src/main.cpp     | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/renderer.cpp |  37 ++++++++++++++++
 src/renderer.h   |  15 +++++++
 src/texture.cpp  |  46 +++++++++++++++++++
 src/texture.h    |  15 +++++++
 src/timer.cpp    |  19 ++++++++
 src/timer.h      |  15 +++++++
 src/window.cpp   |  58 ++++++++++++++++++++++++
 src/window.h     |  27 ++++++++++++
 12 files changed, 392 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Makefile
 create mode 100644 manifest.scm
 create mode 100644 src/main.cpp
 create mode 100644 src/renderer.cpp
 create mode 100644 src/renderer.h
 create mode 100644 src/texture.cpp
 create mode 100644 src/texture.h
 create mode 100644 src/timer.cpp
 create mode 100644 src/timer.h
 create mode 100644 src/window.cpp
 create mode 100644 src/window.h

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..25e7a68
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build/*
+tetris
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3b2fa99
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+CC		= g++
+CFLAGS	= -Wall
+
+TARGET	= tetris
+
+SRCDIR	= src
+
+OBJDIR	= build
+BASENM	= $(notdir $(basename $(wildcard src/*.cpp)))
+OBJS	= $(addsuffix .o, $(addprefix $(OBJDIR)/, $(BASENM)) )
+
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+	$(CC) $(OBJS) -o $(TARGET) -lSDL2 -lSDL2_image
+
+$(OBJS): $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
+	mkdir -p $(OBJDIR)
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+	rm -r $(OBJDIR) $(TARGET)
+
+.PHONY: all clean
diff --git a/manifest.scm b/manifest.scm
new file mode 100644
index 0000000..3606f15
--- /dev/null
+++ b/manifest.scm
@@ -0,0 +1 @@
+(specifications->manifest '("sdl2" "sdl2-image" "gcc-toolchain" "gdb" "man-db"))
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..422fdc3
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,132 @@
+//Using SDL and standard IO
+#include <SDL2/SDL.h>
+#include <stdio.h>
+#include "texture.h"
+#include "renderer.h"
+#include "window.h"
+#include "timer.h"
+
+#include <chrono>
+#include <thread>
+//void millisleep(Uint32 t){
+//    SDL_Delay(t);
+//}
+
+//Screen dimension constants
+const int SCREEN_WIDTH = 640;
+const int SCREEN_HEIGHT = 480;
+const int WALKING_ANIMATION_FRAMES = 7;
+
+void loop( Renderer &renderer, Texture &gSpriteSheetTexture, SDL_Rect* gSpriteClips, Uint32 dt){
+    static int frame;
+
+    renderer.clear();
+    SDL_Rect* currentClip = &gSpriteClips[ frame / WALKING_ANIMATION_FRAMES ];
+
+
+    // Txanpona mugitu:
+    float vx = 100; // px/s
+    static float xpos0;
+    float xpos = xpos0 + dt/1000.f * vx;
+    xpos0 = xpos;
+
+    float g = 75; // px/(s^2)
+    static float vy0 = 100; // px/s
+    static float ypos0;
+    float vy = vy0 -(dt/1000.f * g) ;
+    float ypos = ypos0 + dt/1000.f * vy;
+    ypos0 = ypos;
+    vy0 = vy;
+    if ( ypos0 < 0 ) { ypos0 = 0; }
+    if ( ypos < 0 ) { ypos = 0; }
+
+    gSpriteSheetTexture.render(xpos, (SCREEN_HEIGHT/2 -20) - ypos, currentClip);
+
+    //Update screen
+    renderer.update();
+    ++frame;
+
+    //Cycle animation
+    if( frame / WALKING_ANIMATION_FRAMES >= WALKING_ANIMATION_FRAMES )
+    {
+        frame = 0;
+    }
+    return;
+
+}
+
+int
+main( int argc, char* args[] ) {
+
+    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
+    {
+        printf( "SDL could not initialize: %s\n", SDL_GetError() );
+    }
+
+    Window window {"This is the title", SCREEN_WIDTH, SCREEN_HEIGHT};
+    Renderer renderer;
+    renderer.init(window.window());
+    renderer.setScale(2,2);
+
+
+    //The window we'll be rendering to
+    SDL_Rect gSpriteClips[ WALKING_ANIMATION_FRAMES ];
+    Texture gSpriteSheetTexture {renderer.renderer()};
+
+
+    //Load sprite sheet texture
+    if(-1 ==gSpriteSheetTexture.loadFromFile( "assets/money.png" ) )
+    {
+        return -1;
+    }
+    else
+    {
+        for( int i =0; i < WALKING_ANIMATION_FRAMES; i++){
+            //Set sprite clips
+            gSpriteClips[ i ].x = i*16;
+            gSpriteClips[ i ].y =    0;
+            gSpriteClips[ i ].w =   16;
+            gSpriteClips[ i ].h =   16;
+        }
+    }
+
+
+    // BODY
+    ///////////////////////////////////////////////////////////////////////////
+    const Uint32 LOOP_TIME = 20L; // milliseconds
+    Timer timer;
+    timer.start();
+    while( true )
+    {
+        // Handle events
+        SDL_Event e;
+        while( SDL_PollEvent( &e ) != 0 )
+        {
+            //User requests quit
+            window.handleEvent(e);
+            if( e.type == SDL_QUIT ) {
+                return 0;
+            } else if (e.type == SDL_KEYDOWN){
+                switch( e.key.keysym.sym ){
+                    case 'q':
+                        return 0;
+                }
+            }
+        }
+
+        if(window.closed()) return 0;
+        if(!window.focused()) goto next;
+
+
+        // GAME LOOP:
+        loop(renderer, gSpriteSheetTexture, gSpriteClips, timer.elapsed());
+
+        // Loop time calculation:
+    next:
+        timer.restart();
+        timer.waitUntil( LOOP_TIME );
+    }
+
+    SDL_Quit();
+    return 0;
+}
diff --git a/src/renderer.cpp b/src/renderer.cpp
new file mode 100644
index 0000000..2f90a8d
--- /dev/null
+++ b/src/renderer.cpp
@@ -0,0 +1,37 @@
+#include "renderer.h"
+
+Renderer::Renderer(){
+    renderer_ = nullptr;
+}
+
+Renderer::~Renderer(){
+    SDL_DestroyRenderer(renderer_);
+}
+
+void Renderer::init( SDL_Window* win ) {
+    if (renderer_){
+        SDL_DestroyRenderer(renderer_);
+    }
+    renderer_ = SDL_CreateRenderer( win, -1, SDL_RENDERER_ACCELERATED);
+    if (renderer_ == NULL){
+        printf("Unable to create rendering context: %s", SDL_GetError());
+    }
+}
+
+void Renderer::clear(){
+    SDL_RenderClear(renderer_);
+}
+void Renderer::update(){
+    SDL_RenderPresent(renderer_);
+}
+
+SDL_Renderer * Renderer::renderer(){
+    return renderer_;
+}
+
+void Renderer::setScale(int scaleX, int scaleY){
+    if( SDL_RenderSetScale(renderer_, scaleX, scaleY) < 0){
+        printf("Unable to set scale in renderer: %s", SDL_GetError());
+    }
+}
+
diff --git a/src/renderer.h b/src/renderer.h
new file mode 100644
index 0000000..b76b831
--- /dev/null
+++ b/src/renderer.h
@@ -0,0 +1,15 @@
+#include <SDL2/SDL.h>
+
+class Renderer{
+
+    public:
+        Renderer();
+        ~Renderer();
+        void init(SDL_Window* win);
+        void clear();
+        void update();
+        SDL_Renderer* renderer();
+        void setScale(int scaleX, int scaleY);
+    private:
+        SDL_Renderer* renderer_;
+};
diff --git a/src/texture.cpp b/src/texture.cpp
new file mode 100644
index 0000000..6657a4a
--- /dev/null
+++ b/src/texture.cpp
@@ -0,0 +1,46 @@
+#include <SDL2/SDL_image.h>
+#include "texture.h"
+
+Texture::Texture(SDL_Renderer* renderer):
+    texture_(nullptr),
+    w_(0),
+    h_(0),
+    renderer_ (renderer){
+}
+
+Texture::~Texture(){
+    if(texture_){
+        SDL_DestroyTexture(texture_);
+    }
+}
+
+int Texture::loadFromFile(std::string path){
+    SDL_Surface* Loading_Surf = IMG_Load(path.c_str());
+    if(Loading_Surf == NULL){
+        printf("Failed to load surface: %s\n", SDL_GetError());
+        return -1;
+    }
+    texture_ = SDL_CreateTextureFromSurface(renderer_, Loading_Surf);
+    if(texture_ == NULL){
+        printf("Failed to create texture: %s\n", SDL_GetError());
+        return -1;
+    }
+    SDL_FreeSurface(Loading_Surf);
+    w_ = Loading_Surf->w;
+    h_ = Loading_Surf->h;
+    return 0;
+}
+
+void Texture::render(int x, int y, SDL_Rect* clip){
+    SDL_Rect renderQuad = { x, y, w_, h_ };
+
+    //Set clip rendering dimensions
+    if( clip )
+    {
+        renderQuad.w = clip->w;
+        renderQuad.h = clip->h;
+    }
+
+    //Render to screen
+    SDL_RenderCopy( renderer_, texture_, clip, &renderQuad );
+}
diff --git a/src/texture.h b/src/texture.h
new file mode 100644
index 0000000..311db4a
--- /dev/null
+++ b/src/texture.h
@@ -0,0 +1,15 @@
+#include <SDL2/SDL.h>
+#include <string>
+
+class Texture{
+    public:
+        Texture(SDL_Renderer* renderer);
+        ~Texture();
+        int loadFromFile(std::string path);
+        void render(int x, int y, SDL_Rect* clip = nullptr);
+    private:
+        SDL_Texture* texture_;
+        int w_;
+        int h_;
+        SDL_Renderer* renderer_;
+};
diff --git a/src/timer.cpp b/src/timer.cpp
new file mode 100644
index 0000000..c775a73
--- /dev/null
+++ b/src/timer.cpp
@@ -0,0 +1,19 @@
+#include "timer.h"
+
+Timer::Timer(): t0 {0} {}
+
+void Timer::start(){
+    t0 = SDL_GetTicks();
+}
+unsigned int Timer::elapsed(){
+    return SDL_GetTicks() - t0;
+}
+void Timer::restart(){
+    start();
+}
+void Timer::wait(unsigned int millis){
+    SDL_Delay(millis);
+}
+void Timer::waitUntil(unsigned int millis){
+    wait( millis - elapsed() );
+}
diff --git a/src/timer.h b/src/timer.h
new file mode 100644
index 0000000..3c714a9
--- /dev/null
+++ b/src/timer.h
@@ -0,0 +1,15 @@
+#include<SDL2/SDL.h>
+class Timer{
+
+    public:
+        Timer();
+
+        void start();
+        unsigned int elapsed();
+        void restart();
+        void wait(unsigned int millis);
+        void waitUntil(unsigned int millis);
+
+    private:
+        Uint32 t0;
+};
diff --git a/src/window.cpp b/src/window.cpp
new file mode 100644
index 0000000..39cbc3d
--- /dev/null
+++ b/src/window.cpp
@@ -0,0 +1,58 @@
+#include "window.h"
+
+Window::Window( const char* title, int w, int h, int x, int y )
+    : closed_ {false},
+      focused_ {true} {
+    window_ = SDL_CreateWindow( title, x, y, w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE );
+    if( window_ == NULL )
+    {
+        printf( "Window could not be created: %s\n", SDL_GetError() );
+    }
+}
+
+Window::~Window(){
+    SDL_DestroyWindow( window_ );
+}
+
+SDL_Window* Window::window(){
+    return window_;
+}
+
+void Window::toggleFullscreen(){
+    auto togg = SDL_TRUE;
+    if( fullscreen_ ){
+        togg = SDL_FALSE;
+    }
+    SDL_SetWindowFullscreen( window_, togg );
+    printf("toggling fullscreen\n");
+    fullscreen_ = !fullscreen_;
+}
+
+void Window::handleEvent(SDL_Event e){
+    switch( e.window.event ){
+        case SDL_WINDOWEVENT_CLOSE:
+            closed_ = true;
+            printf("CLOSE!");
+            break;
+        case SDL_WINDOWEVENT_FOCUS_GAINED:
+            focused_ = true;
+            break;
+        case SDL_WINDOWEVENT_FOCUS_LOST:
+            focused_ = false;
+            break;
+    }
+}
+
+Point Window::getSize(){
+    Point size;
+    SDL_GetWindowSize(window_, &size.x, &size.y);
+    return size;
+}
+
+bool Window::focused(){
+    return focused_;
+}
+
+bool Window::closed(){
+    return closed_;
+}
diff --git a/src/window.h b/src/window.h
new file mode 100644
index 0000000..efa2165
--- /dev/null
+++ b/src/window.h
@@ -0,0 +1,27 @@
+#include<SDL2/SDL.h>
+
+struct Point{
+    int x, y;
+};
+
+class Window{
+
+    public:
+        Window( const char * title,
+                int w,
+                int h,
+                int x = SDL_WINDOWPOS_UNDEFINED,
+                int y = SDL_WINDOWPOS_UNDEFINED );
+        ~Window();
+        SDL_Window* window();
+        void handleEvent( SDL_Event e );
+        void toggleFullscreen();
+        Point getSize();
+        bool closed();
+        bool focused();
+    private:
+        SDL_Window* window_;
+        bool fullscreen_;
+        bool focused_;
+        bool closed_;
+};
-- 
cgit v1.2.3