G
Ich weiß nicht ob es dir hilft, aber ich habe mal den Mode 7 in SDL2 umgesetzt. Ursprünglich kommt diese Idee aus diesem Artikel:
http://www.helixsoft.nl/articles/circle/sincos.htm
Vielleicht hilft es dir. Ich ziege dir hier mal meine Klasse:
#ifndef CGRAPHIC_H
#define CGRAPHIC_H
#include <SDL2/SDL.h>
typedef struct mode7params
{
int space_z;
int horizon;
int scalex,scaley;
};
class cgraphic
{
public:
cgraphic(int resx,int resy);
virtual ~cgraphic();
void render(SDL_Surface* screen);
void SetFullscreen(int i);
void mode7(SDL_Surface *bmp,SDL_Surface *tile, float angle,float cx, float cy, mode7params *params);
void putpixel(SDL_Surface *bmp ,int x,int y,int c);
Uint32 getpixel(SDL_Surface *bmp ,int x,int y);
SDL_Surface* screen;
protected:
private:
SDL_Window *window;
};
#endif // CGRAPHIC_H
#include "cgraphics.h"
#include <stdio.h>
#include <math.h>
cgraphic::cgraphic(int resx,int resy)
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"Mode7",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
resx,
resy,
SDL_WINDOW_OPENGL|SDL_WINDOW_FULLSCREEN
);
if (window == NULL) {
printf("Could not create window: %s\n", SDL_GetError());
delete this;
}
screen = SDL_GetWindowSurface( window );
}
cgraphic::~cgraphic()
{
SDL_DestroyWindow(window);
SDL_Quit();
}
void cgraphic::render(SDL_Surface* screen)
{
SDL_UpdateWindowSurface(window);
}
void cgraphic::SetFullscreen(int i)
{
SDL_SetWindowFullscreen(window,i);
}
void cgraphic::mode7 (SDL_Surface *screen,SDL_Surface *tile, float angle,float cx, float cy, mode7params *params)
{
float screenx,screeny,
distance,horizonscale;
int maskx=tile->w-1,
masky=tile->h-1;
float spacex,spacey,
linex,liney;
for (screeny=140; screeny < screen->h;screeny++)
{
distance = (params->space_z * params->scaley) / (screeny + params->horizon);
horizonscale=(distance / params->scalex);
linex= (-SDL_sinf(angle) * horizonscale);
liney= (SDL_cosf(angle) * horizonscale);
spacex=cx+(distance * SDL_cosf(angle))- screen->w/2 * linex;
spacey=cy+(distance * SDL_sinf(angle))- screen->h/2 * liney;
for (screenx=0; screenx < screen->w;screenx++)
{
putpixel (screen,
(int)screenx,
(int)screeny,
getpixel (tile,
(int)spacex &maskx,
(int)spacey &masky ));
spacex += linex;
spacey += liney;
}
}
}
void cgraphic::putpixel(SDL_Surface *bmp,int x, int y, int c)
{
int bpp = bmp->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)bmp->pixels + y * bmp->pitch + x * bpp;
switch(bpp) {
case 1:
*p = c;
break;
case 2:
*(Uint16 *)p = c;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (c >> 16) & 0xff;
p[1] = (c >> 8) & 0xff;
p[2] = c & 0xff;
} else {
p[0] = c & 0xff;
p[1] = (c >> 8) & 0xff;
p[2] = (c >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = c;
break;
}
}
Uint32 cgraphic::getpixel(SDL_Surface *bmp, int x, int y)
{
int bpp = bmp->format->BytesPerPixel;
Uint8 *p = (Uint8 *)bmp->pixels + y * bmp->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
break;
case 2:
return *(Uint16 *)p;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;
case 4:
return *(Uint32 *)p;
break;
default:
return 0;
}
}
#include <iostream>
#include "cgraphics.h"
#include <SDL2/SDL.h>
using namespace std;
cgraphic *g;
SDL_Event e;
SDL_Surface *tile,*bg;
float posx=100,posy=100;
int quit;
float angle=0;
bool moveup,turnleft,turnright;
mode7params params;
void ControlCheck();
int main()
{
g=new cgraphic(800,600);
tile=SDL_LoadBMP("map2.bmp");
bg=SDL_LoadBMP("bg.bmp");
params.horizon=-130;
params.scalex=500;
params.scaley=500;
params.space_z=15;
while (!quit)
{
if (moveup==true)
{
posx+=SDL_cosf(angle)*1.5;
posy+=SDL_sinf(angle)*1.5;
}
if(turnleft==true)
angle-=0.01;
if(turnright==true)
angle+=0.01;
SDL_FillRect(g->screen,NULL,SDL_MapRGB(g->screen->format,0x00,0x00,0x00));
SDL_BlitSurface(bg,NULL,g->screen,NULL);
g->mode7(g->screen,tile,angle,posx,posy,¶ms);
g->render(g->screen);
ControlCheck();
}
delete g;
return 0;
}
void ControlCheck()
{
while(SDL_PollEvent(&e))
{
const Uint8*KeyStates=SDL_GetKeyboardState(NULL);
turnleft=false;
turnright=false;
moveup=false;
if (KeyStates[SDL_SCANCODE_ESCAPE])
{
quit=true;
}
//--------------------------------------
if (KeyStates[SDL_SCANCODE_UP])
{
moveup=true;
}
if (KeyStates[SDL_SCANCODE_DOWN])
{
posx-=SDL_cosf(angle)*2;
posy-=SDL_sinf(angle)*2;
}
if (KeyStates[SDL_SCANCODE_LEFT])
turnleft=true;
if (KeyStates[SDL_SCANCODE_RIGHT])
turnright=true;
if(e.type==SDL_QUIT)
quit=true;
}
}
Viele Grüße
Guitarlo