跳转到内容

Aros/开发者/SDL

来自Wikibooks,开放世界中的开放书籍
Aros维基百科的导航栏
Aros用户
Aros用户文档
Aros用户常见问题
Aros用户应用程序
Aros用户DOS Shell
Aros/用户/AmigaLegacy
Aros开发文档
Aros开发者文档
从AmigaOS/SDL移植软件
Zune初学者指南
Zune .MUI类
SDL初学者指南
Aros开发者构建系统
特定平台
Aros x86完整系统HCL
Aros x86音频/视频支持
Aros x86网络支持
Aros Intel AMD x86安装
Aros存储支持IDE SATA等
Aros Poseidon USB支持
x86-64支持
Motorola 68k Amiga支持
Linux和FreeBSD支持
Windows Mingw和MacOSX支持
Android支持
Arm Raspberry Pi支持
PPC Power Architecture
其他
Aros公共许可证
SDL_Init
    SDL_SetVideoMode 
    SDL_Surface
    SDL_Rect

    SDL_PollEvent 
        SDL_EventType

SDL_FreeSurface
SDL_Quit

许多SDL游戏通过轮询(即持续读取)事件队列来工作。

https://wiki.libsdl.org/SDL_PollEvent

示例代码展示了丑陋的while(1) { SDL_PollEvent(...); }。

它会占用任何CPU资源。

更好的主循环是使用SDL_WaitEvent/SDL_WaitEventTimeout。

https://wiki.libsdl.org/SDL_WaitEvent https://wiki.libsdl.org/SDL_WaitEventTimeout

至少,这些调用不应该占用所有CPU。

C语言初始化SDL

[编辑 | 编辑源代码]

C++初始化SDL

[编辑 | 编辑源代码]
#include <SDL/SDL.h>

#include "Application.h"

//Extern'd in Application.h; Used as forefront to access everything we create =D
Application* pApp;

int main(int args, char* argv[])
{
    //Create the application on the heap for actual use
    pApp = new Application();

    //Initialize the application. If something fails, return -1 (I like -1 for errors)
    if(pApp->Init() != true)
    {
        return -1;
    }

    //This should successfully run our application
    //Should go through Input, Logic, and Rendering
    pApp->Run();

    //This will clean up everything, deallocating dynamically allocated memory
    //Uninitializing SDL, etc.
    pApp->Quit();

    //Out of habit, I always check to make sure a pointer has a value (other than NULL)
    //Before I deallocate it. I also ALWAYS set it to NULL immediately after.
    //Good habit to get into because it is preventative for memory leaks
    if(pApp)
    {
        delete pApp;
        pApp = NULL;
    }

    //Lastly, end the application, returning 0 to indicate that nothing went wrong
    return 0;
}
#ifndef APPLICATION_H_INCLUDED
#define APPLICATION_H_INCLUDED

#include <SDL/SDL.h>

class Application
{
private:
    //We'll keep adding here as we go along

    bool m_bDone;
public:
    Application();
    ~Application();

    bool Init();
    void Run();
    void TakeInput(SDL_Event* pEvent);
    void Update();
    void Render();
    void Quit();
};

//We'll use this global pointer to access things like the window later on
extern Application* pApp;

#endif // APPLICATION_H_INCLUDED
#include "Application.h"

Application::Application()
{
    //Standard constructor we'll use to initialize variables with default values

    //The program just started, we certainly are not done yet!
    m_bDone = false;
}

Application::~Application()
{
    //Here, we'll deallocate any dynamically allocated memory we may have missed
}

bool Application::Init()
{
    //Initialize SDL and return false if anything goes wrong
    //We'll add more initializations here for anything else we use
    if(SDL_Init(SDL_INIT_EVERYTHING) != 0)
    {
        return false;
    }

    //Lastly return true to indicate that the initialization was successful
    return true;
}

void Application::Run()
{
    //This function implements our loop
    //Any calls that should be made each frame should be put in this loop

    //the m_bDone variable will track whether the program is ready to exit
    while(!m_bDone)
    {
        m_bDone = true;
    }
}

void Application::TakeInput(SDL_Event* pEvent)
{
    //We'll use this function to take input from the user and act upon it
}

void Application::Update()
{
    //This is where all the magic happens!
    //After receiving input, this is where we act on that input
    //and actually make things happen =D
}

void Application::Render()
{
    //Here, we will draw our images to the screen
}

void Application::Quit()
{
    //Uninitialize SDL, we'll also deallocate any memory we dynamically allocate
    SDL_Quit();
}

2D平台游戏伪代码

[编辑 | 编辑源代码]
game loop

while( SDL_PollEvent( &event ) )
      {
        myHero.handle_input();
            //If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
        }

    
    myHero.move( blahbox );
    
    //Set the camera
    myHero.set_camera();

handle_input()

    if( event.type == SDL_KEYDOWN )
    {
        
            if( SDLK_LEFT ) { xForce -= HERO_WIDTH / 2; }
        
            if( SDLK_RIGHT ){ xForce += HERO_WIDTH / 2; }

    }
    else if( event.type == SDL_KEYUP )
    {

            if( SDLK_LEFT ) { xForce = 0; }
            if( SDLK_RIGHT ) { xForce = 0; }

    }

move()

void Hero::move(SDL_Rect blahbox)
{
    //Move the dot left or right
    if( xForce != 0 ) { xAcc = xForce / HERO_MASS; }
    if( xForce == 0 ) { xVel = xAcc = 0; }
    xVel = xVel + xAcc;
    box.x = box.x + xVel;

    //If the dot went too far to the left or right or touched a wall
    if( ( box.x < 0 ) || ( box.x + HERO_WIDTH > LEVEL_WIDTH ) || check_collision( box, blahbox) )
    {
        //move back
        box.x = box.x - xVel;
    }

}

what i was going for is force is applied when a key is pressed,

acceleration = Force / Mass
Velocity = Velocity + Acceleration
etc...

游戏例程

[编辑 | 编辑源代码]
/* Here's the include */
#include "SDL.h"

SDL_Surface* screen;

void startGame()
{
    /* Load my picture */
    SDL_Surface* pic = SDL_LoadBMP("mypic.bmp");

    /* Here's where I'll draw it */
    SDL_Rect destRect;
    if(pic != NULL)
    {
        destRect.x = screen->w/2 - pic->w/2;
        destRect.y = screen->h/2 - pic->h/2;
    }

    /* Here are two rectangles */
    /* I initialize rect.x, rect.y, rect.w, and rect.h all at once */
    SDL_Rect rect1 = {40, 40, 300, 200};
    SDL_Rect rect2 = {200, 100, 160, 160};

    /* Start the main loop */
    SDL_Event event;
    Uint8 done = 0;
    while (!done)
    {
        /* Check for events */
        while (SDL_PollEvent(&event))
        {
            if(event.type == SDL_QUIT)
            {
                done = 1;
            }
            if(event.type == SDL_KEYDOWN)
            {
                if(event.key.keysym.sym == SDLK_ESCAPE)
                {
                    done = 1;
                }
            }
        }

        /* Clear the screen */
        SDL_FillRect(screen, NULL, 0x000000);
        
        /* Red rectangle */
        SDL_FillRect(screen, &rect1, SDL_MapRGB(screen->format, 200, 0, 0));

        /* White rectangle */
        SDL_FillRect(screen, &rect2, SDL_MapRGB(screen->format, 255, 255, 255));

        /* Draw my picture */
        SDL_BlitSurface(pic, NULL, screen, &destRect);

        /* Send all this to the monitor */
        SDL_Flip(screen);
    }
    
    /* Free up the picture memory */
    SDL_FreeSurface(pic);

    return;
}

int main(int argc, char *argv[])
{
    /* Initialize SDL */
    if( SDL_Init(SDL_INIT_VIDEO) < 0 )
        return 0;

    /* Initialize the screen surface */
    screen = SDL_SetVideoMode(400, 300, 32, SDL_SWSURFACE);
    if ( screen == NULL )
        return 0;

    /* Now do whatever we want! */
    startGame();

    SDL_Quit();
    return 0;
}

如果SDL失败

if( SDL_Init( SDL_INIT_VIDEO ) == -1 )
{
   fprintf(stderr, "Failed to initialize SDL. [%s]\n", SDL_GetError());
   exit(1);
}
SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
if( screen == NULL )
{
   fprintf(stderr, "Failed to set video mode. [%s]\n", SDL_GetError());
   exit(1);
}
SDL_Event evt;
bool done = false;
 
while( !done )
{
        while( SDL_PollEvent( &evt ) )
	{
		switch( evt.type )
		{
		case SDL_QUIT:
		  done = true;
		  break;
 
		case SDL_KEYUP:
		  if( evt.key.keysym.sym == SDLK_ESCAPE )
		       done = true;
		  break;
            default:
                  break;
		}
	}
}
#include <sdl.h>
 
int main( int argc, char **argv)
{
	SDL_Event evt;
	bool done = false;
 
	// initialize SDL
	if( SDL_Init( SDL_INIT_VIDEO ) == -1 )
	{
            fprintf(stderr, "Failed to initialize SDL. [%s]\n", SDL_GetError());
            exit(1);
	}
 
	// create a software surface/window
	SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
        if( screen == NULL )
        {
            fprintf(stderr, "Failed to set video mode. [%s]\n", SDL_GetError());
            exit(1);
        }
 
	// main game loop
	while( !done )
	{
		// check for events generated from SDL
		while( SDL_PollEvent( &evt ) )
		{
			switch( evt.type )
			{
			case SDL_QUIT:
				done = true;
				break;
 
			case SDL_KEYUP:
				if( evt.key.keysym.sym == SDLK_ESCAPE )
					done = true;
				break;
 
			default:
				break;
			}
		}
	}
 
	SDL_Quit();
 
	return 0;
}
Uint32 color1 = SDL_MapRGB(screen->format, 0x00, 0x00, 0xFF);
Uint32 color2 = SDL_MapRGB(screen->format, 0x00, 0xFF, 0x00);
Uint32 currentColor = color1;
case SDL_KEYUP:
   if( evt.key.keysym.sym == SDLK_ESCAPE )
      done = true;
   else if( evt.key.keysym.sym == SDLK_SPACE )
   {
      currentColor = ( currentColor == color1 ) ? color2 : color1;
      SDL_FillRect( screen, NULL, currentColor);
      SDL_UpdateRect(screen, 0, 0, 0, 0);
   }
   break;
case SDL_KEYDOWN:
   printf( "KEYDOWN: %c\n", evt.key.keysym.unicode);
   break;
//SDL_Mixer 
#include <SDL/SDL_mixer.h>

//
Mix_Chuck* effect1;
Mix_Chuck* effect2;
Mix_Music* music;
Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,4096);
music=Mix_LoadMUS("sound.wav");
effect1=Mix_LoadWAV("sound.wav");
effect2=Mix_LoadWAV("sound2.wav");

screen=SDL_SetVideoMode(x,y,res,SDL_SWSURFACE);

//in events loop
Mix_PlayMusic(music-1);

case SDL_KEYDOWN:
     switch(event.key,keysym.sym)
     {
		 case SDLK_1:
		     Mix_PlayChannel(-1,effect1,0);
		 case SDLK_1:
		     Mix_PlayChannel(-1,effect2,0);
	 }

//close
Mix_FreeChuck(effect2);
Mix_FreeChuck(effect1);
Mix_FreeMusic(music);
Mix_CloseAudio;

SDL_QUIT();
//This program is made by thecplusplusguy from YouTube for demonstration purposes.
//Feel free to read, learn, or modify the source as you wish, LGPL licence, I guess.
//http://www.youtube.com/user/thecplusplusguy
//keep this header comment for advertisement :) 
//compile in case of Windows normally, in case of Linux normally as well, so:
//g++ particle.cpp -lSDL
//Code::blocks: build and run
#include <SDL/SDL.h>
#include <iostream>
#include <vector>	//to store the particles (I like std::vector :D)
#include <cstdlib>	//for the random numbers
#include <ctime>

class particle{	//represent 1 particle
	float x,y,xvel,yvel;	//position && speed
	Uint32 endTime;	//death time
	Uint8 color;	//color
	public:
	particle(float X,float Y,float Xvel,float Yvel,int life,Uint8 Color);
	void move();
	void show();
	bool isDead();	//true if the particle dead else false
};

particle::particle(float X,float Y,float Xvel,float Yvel,int life,Uint8 Color)
{
	//initialize the variables, nothing new
	x=X;
	y=Y;
	xvel=Xvel;
	yvel=Yvel;
	endTime=SDL_GetTicks()+life; //the end time, is the current time + the time, while the particle lives
	color=Color;
}

void particle::move()
{
	//move
	x+=xvel;
	y+=yvel;
	//if it is outside of the screen, set it back to the edge of the screen
	if(x<0)
		x=0;
	if(y<0)
		y=0;
	if(x>SDL_GetVideoSurface()->w)
		x=SDL_GetVideoSurface()->w-1;
	if(y>SDL_GetVideoSurface()->h)
		y=SDL_GetVideoSurface()->h-1;
}

void particle::show()
{
	//just set the pixel to the current color at the current position (pixel manipulation tutorial)
	Uint8* pixels=(Uint8*)SDL_GetVideoSurface()->pixels;
	Uint8* pixel=pixels+(int)y*SDL_GetVideoSurface()->pitch+(int)x;
	*pixel=color;
}

bool particle::isDead()
{
	//read above, what it does
	return (SDL_GetTicks()>=endTime || x==0 || y==0 || x==SDL_GetVideoSurface()->w-1 || y==SDL_GetVideoSurface()->h-1);
}
//the particle engine will store all of the particle, and their initialize position
class particleEngine{
	std::vector<particle*> particles;	//this vector represent all of the particle
	int x,y,maxparticle;
	public:
	particleEngine(int maxpart,int X, int Y);
	~particleEngine();	//need for deallocate allocated space
	void refresh();	//move && show the particles
};

particleEngine::particleEngine(int maxpart,int X, int Y)
{
	x=X;
	y=Y;
	maxparticle=maxpart;
	for(int i=0;i<maxparticle;i++)	//create maxparticle number of particles with random values both for position, velocity, life, color
		particles.push_back(new particle(x+rand()%6-3,y+rand()%6-3,rand()%10+(float)rand()/(float)RAND_MAX-5,rand()%10+(float)rand()/(float)RAND_MAX-5,500+rand()%1000,rand()%255));
}

particleEngine::~particleEngine()
{
	//deallocate all reserved memory
	for(int i=0;i<maxparticle;i++)
		delete particles[i];
}

void particleEngine::refresh()
{
	for(int i=0;i<maxparticle;i++)
	{
		if(particles[i]->isDead())	//if dead
		{
			delete particles[i];	//delete the earlier one and create a new
			particles[i]=new particle(x+rand()%6-3,y+rand()%6-3,rand()%10+(float)rand()/(float)RAND_MAX-5,rand()%10+(float)rand()/(float)RAND_MAX-5,500+rand()%2000,rand()%255);
		}else{	//else
			particles[i]->move();	//move && show
			particles[i]->show();
		}
	}
}

int main(int argc,char** argv)
{
	//this should be familiar to you
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Surface* screen;
	screen=SDL_SetVideoMode(640,480,8,SDL_SWSURFACE);	
	bool running=true;
	const int FPS=30;	//make the FPS bigger, for quicker animation
	Uint32 start;
	srand(time(0));	//seed the random number generator
	particleEngine ps(5000,screen->w/2,screen->h/2);	//create the particles
	while(running)
	{
		start=SDL_GetTicks();
		SDL_Event event;
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
					running=false;
					break;
			}
		}

	SDL_FillRect(screen,&screen->clip_rect,SDL_MapRGB(screen->format,0x00,0x00,0x00));	//clear the screen
		//logic
	ps.refresh();	//refresh the particles

	SDL_Flip(screen);
		if(1000/FPS>SDL_GetTicks()-start)
			SDL_Delay(1000/FPS-(SDL_GetTicks()-start));
	}
	SDL_Quit();
	return 0;
}

参考文献

[编辑 | 编辑源代码]

综合教程

SDL OpenGL和LUA

教程

C++教程

Alpha混合

教程

2D引擎

SDL音频输入示例

编程论坛

libSDL.a
libSDL_gfx.a
libSDLGL.a
libSDL_image.a
libSDL_mixer.a
libSDL_net.a
libSDL_sound.a
libSDL_ttf.a

分步教程 俄罗斯方块

SDL使用基于事件的输入。所有SDL应用程序都自行处理事件。因此,每个SDL应用程序在AROS上启动一个繁忙循环,尽可能多地占用CPU时间。似乎SDL软件编写得也不好,大部分代码使用事件轮询(而不是等待事件)和小延迟,例如此处。似乎许多程序员根本不在乎SDL游戏即使在空闲状态下是否消耗100%的CPU时间。

st=SDL_GetAppState();
if ((st==SDL_APPACTIVE) || (! st) ) SDL_Delay(1000)
else SDL_Delay(0)
PollEvents...
...

SDL中的颜色通常存储在Uint32变量中。此类型(以及其他类型)由SDL定义,以便您可以确保在每个不同的平台/操作系统上获得精确的32位,而不是模棱两可的“unsigned int”。在32位表面上,每个颜色分量获得8位。如果我这样写一个十六进制常量:0x50a600ff,并且像素格式为ARGB,那么我的分量将是alpha = 0x50(80),red = 0xa6(166),green = 0x00(0),blue = 0xff(255)。在那里您可以看到颜色分量范围从0到255(256个值)。这些分量可以分别存储在Uint8变量中。

SDL使用计算机图形的标准坐标轴。点(0,0)位于屏幕的左上角。x坐标向右增加,y坐标向下增加。这确实有一个小的副作用,即坐标系是左手系(角度按顺时针方向测量)。

将某些内容包装在您自己的函数中是值得的。例如,您可以编写一个将图像绘制到屏幕上的函数,只需传入表面指针和坐标即可。发现将键盘和操纵杆处理都包装到一个函数中非常容易,因此我的游戏接受任一输入方法作为特定玩家的输入,并且使用它的代码很简洁。

旧式OpenGL 1.1 - 立即模式:glBegin()、glEnd()、glVertex()等

新式OpenGL 2 3 4 - 顶点数组

OpenGL 2、3和4 - 着色器等

[编辑 | 编辑源代码]

glColor() - 即使经常与立即模式一起使用,这对于为后续要绘制的顶点设置常量颜色也是可以的。

glNormal()、glTexCoord() - 与glColor()类似,尽管设置这些为常量值的情况很少见。

glTranslate()、glLoadMatrix()、glMultMatrix()等 - 这些是进行变换的方式。

glMatrixMode() - 用于更改要应用更改的矩阵。不要在每一帧都执行glFrustum()、glOrtho()、gluPerspective()或类似操作(除非其参数发生更改)。在大多数情况下,这属于您的重塑函数。

NOTE: all of the previous functionality is deprecated, and done quite differently in "modern" OpenGL

glEnableClientState()、glVertexPointer()(以及法线、纹理坐标、颜色的等效项)、glDrawArrays()、glDrawElements() - 虽然已弃用,但“理念”通常与现代OpenGL相同(但使用的函数不同)。为OpenGL提供指向元素的指针,它将绘制这些元素。当然,在可能的情况下,您希望使用VBO(将数据上传到显存)。如果您希望将代码也编译到已支持它的平台上,可以使用一些#ifdef来做到这一点。

GL_POINTS、GL_LINES、GL_LINE_STRIP、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN - 这些仍然存在于每个OpenGL(或OpenGL ES)实现中。随意使用。

注意:所有先前功能(立即模式除外)都适用于OpenGL ES1。OpenGL ES2广泛使用着色器,并且如果不使用大量#ifdef或类似方法,则无法编写既适用于TinyGL或OpenGL1又适用于OpenGL ES2的代码,假设您执行的操作比使用指定颜色清除屏幕更复杂。

GL_QUADS、GL_QUAD_STRIP、GL_POLYGON - 避免使用。已弃用,并且OpenGL ES1和ES2中都没有。改用索引的GL_TRIANGLES或GL_TRIANGLE_STRIP。

http://www.amigacoding.de/index.php?topic=456.0

http://www.amigacoding.de/index.php?topic=494.0

使用纹理图集的VBO(顶点缓冲对象)(使用纹理数组创建一个包含所有纹理的大纹理)- 为每个纹理图集使用多个VBO -

着色器

更优化地使用OpenGL状态机。切换着色器和纹理通常比实际绘制调用开销更大,因此必须以最小化这种切换的方式设计代码,例如,在切换到另一个着色器和/或纹理之前,执行所有需要特定着色器和纹理的绘制调用。

http://forum.unity3d.com/threads/63149-After-playing-minecraft...

光照

阴影

反射

凹凸/视差贴图

OpenGL 1 - 旧版

[编辑 | 编辑源代码]

避免以下内容

//pcguy
#include <iostream>
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>

void init()
{
	glClearColor(0.0,0.0,0.0,1.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0,640.0/480.0,1.0,500.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_TRIANGLES);
		glVertex3f(0.0,2.0,-5.0);
		glVertex3f(-2.0,-2.0,-5.0);
		glVertex3f(2.0,-2.0,-5.0);
	glEnd();
}

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Surface* screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE|SDL_OPENGL);
	bool running=true;
	Uint32 start;
	SDL_Event event;
	init();
	while(running)
	{
		start=SDL_GetTicks();
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
					running=false;
					break;
			}
		}
		display();
		SDL_GL_SwapBuffers();
		if(1000/30>(SDL_GetTicks()-start))
			SDL_Delay(1000/30-(SDL_GetTicks()-start));
	}
	SDL_Quit();
	return 0;
}
int main( int argc, char **argv)
{
        // graphics properties
	const int width = 640;        // width of the game window 
	const int height = 480;       // height of the game window
	const float fov = 45.0f;      // field of view (degrees)
	const float nearClip = 1.0f;  // near clip plane (don't set to zero)
	const float farClip = 100.0f; // far clip plane
 
	// initialize SDL
	if( SDL_Init( SDL_INIT_VIDEO ) == -1 )
	{
              fprintf(stderr, "Failed to initialize SDL. [%s]\n", SDL_GetError());
              exit(1);
	}
 
	// set desired OpenGL attributes prior to selecting a video mode
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );  // use 16 bits for depth buffer
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // enable double buffering
 
	// create an OpenGL surface/window
	SDL_Surface *screen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL);
        if( screen == NULL )
        {
              fprintf(stderr, "Failed to set video mode. [%s]\n", SDL_GetError());
              exit(1);
        }
 
	// initialize OpenGL
	if( SetupOpenGL( width, height, fov, nearClip, farClip) == -1 )
	{
		fprintf( stderr, "Failed to setup OpenGL.\n" );
		exit(1);
	}
 
	// main game loop
	bool done = false;
 
	while( !done )
	{
		RenderScene();
 
		if( ProcessInput() )
			done = true;
	}
 
	SDL_Quit();
 
	return 0;
}
int SetupOpenGL( int width, int height, float fov, float nearClip, float farClip )
{
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
 
	float ar = (GLfloat)width / height; // display aspect ratio
 
	// setup projection matrix
	glMatrixMode(GL_PROJECTION);						
	glLoadIdentity();						
	gluPerspective(fov, ar, nearClip, farClip);
 
	// setup model view matrix
	glMatrixMode(GL_MODELVIEW);			
	glLoadIdentity();
 
	// setup depth buffer
	glClearDepth(1.0f);						
	glEnable(GL_DEPTH_TEST);						
	glDepthFunc(GL_LEQUAL);	
 
	// misc. GL settings
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glShadeModel(GL_SMOOTH);
 
	glViewport( 0, 0, width, height );
 
	return 0;
}
void RenderScene( void )
{
	// render everything for the current frame
 
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
 
	// move off center so the quad is visible
	glTranslatef(-1.0f, 0.0f, -5.0f);
 
	// draw quad as red
	glColor3f( 1.0f, 0.0, 0.0 );
 
	// render the quad
	glBegin(GL_QUADS);						
		glVertex3f(-1.0f, 1.0f, 0.0f);				
		glVertex3f( 1.0f, 1.0f, 0.0f);				
		glVertex3f( 1.0f,-1.0f, 0.0f);				
		glVertex3f(-1.0f,-1.0f, 0.0f);			
	glEnd();
 
	// update display
	SDL_GL_SwapBuffers();
}
bool ProcessInput( void )
{
	// runs the input processing loop
	// returns true if any input has requested the application to exit
 
	SDL_Event evt;
	bool exitFlag = false;
 
	// check for events generated from SDL
	while( SDL_PollEvent( &evt ) )
	{
		switch( evt.type )
		{
		case SDL_QUIT:
			exitFlag = true;
			break;
 
		case SDL_KEYUP:
			if( evt.key.keysym.sym == SDLK_ESCAPE )
				exitFlag = true;
			break;
 
		default:
			break;
		}
	}
 
	return exitFlag;
}
#include <windows.h>
 
#include <gl\gl.h>
#include <gl\glu.h>
 
#include <sdl.h>
#include <sdl_opengl.h>
 
// function prototypes
int SetupOpenGL( int width, int height, float fov, float nearClip, float farClip );
void RenderScene( void );
bool ProcessInput( void );
 
int main( int argc, char **argv)
{
	// graphics properties
	const int width = 640;        // width of the game window 
	const int height = 480;       // height of the game window
	const float fov = 45.0f;      // field of view (degrees)
	const float nearClip = 1.0f;  // near clip plane (don't set to zero)
	const float farClip = 100.0f; // far clip plane
 
	// initialize SDL
	if( SDL_Init( SDL_INIT_VIDEO ) == -1 )
	{
		fprintf(stderr, "Failed to initialize SDL. [%s]\n", SDL_GetError());
		exit(1);
	}
 
	// set desired OpenGL attributes prior to selecting a video mode
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );  // use 16 bits for depth buffer
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // enable double buffering
 
	// create an OpenGL surface/window
	SDL_Surface *screen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL);
        if( screen == NULL )
        {
		fprintf(stderr, "Failed to set video mode. [%s]\n", SDL_GetError());
		exit(1);
        }
 
	// initialize OpenGL
	if( SetupOpenGL( width, height, fov, nearClip, farClip) == -1 )
	{
		fprintf( stderr, "Failed to setup OpenGL.\n" );
		exit(1);
	}
 
	// main game loop
	bool done = false;
 
	while( !done )
	{
		RenderScene();
 
		if( ProcessInput() )
			done = true;
	}
 
	SDL_Quit();
 
	return 0;
}
 
int SetupOpenGL( int width, int height, float fov, float nearClip, float farClip )
{
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
 
	float ar = (GLfloat)width / height; // display aspect ratio
 
	// setup projection matrix
	glMatrixMode(GL_PROJECTION);						
	glLoadIdentity();						
	gluPerspective(fov, ar, nearClip, farClip);
 
	// setup model view matrix
	glMatrixMode(GL_MODELVIEW);			
	glLoadIdentity();
 
	// setup depth buffer
	glClearDepth(1.0f);						
	glEnable(GL_DEPTH_TEST);						
	glDepthFunc(GL_LEQUAL);	
 
	// misc. GL settings
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glShadeModel(GL_SMOOTH);
 
	glViewport( 0, 0, width, height );
 
	return 0;
}
 
void RenderScene( void )
{
	// render everything for the current frame
 
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
 
	// move off center so the quad is visible
	glTranslatef(-1.0f, 0.0f, -5.0f);
 
	// draw quad as red
	glColor3f( 1.0f, 0.0, 0.0 );
 
	// render the quad
	glBegin(GL_QUADS);						
		glVertex3f(-1.0f, 1.0f, 0.0f);				
		glVertex3f( 1.0f, 1.0f, 0.0f);				
		glVertex3f( 1.0f,-1.0f, 0.0f);				
		glVertex3f(-1.0f,-1.0f, 0.0f);			
	glEnd();
 
	// update display
	SDL_GL_SwapBuffers();
}
 
bool ProcessInput( void )
{
	// runs the input processing loop
	// returns true if any input has requested the application to exit
 
	SDL_Event evt;
	bool exitFlag = false;
 
	// check for events generated from SDL
	while( SDL_PollEvent( &evt ) )
	{
		switch( evt.type )
		{
		case SDL_QUIT:
			exitFlag = true;
			break;
 
		case SDL_KEYUP:
			if( evt.key.keysym.sym == SDLK_ESCAPE )
				exitFlag = true;
			break;
 
		default:
			break;
		}
	}
 
	return exitFlag;
}
//

//

//

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//position of light source
float pos[]={-2.0,2.0,3.0,1.0};
glLightfv(GL_LIGHT0,GL_POSITION,pos);
//diffused
float dif[]={1.0,1.0,1.0,1.0};
glLightfv(GL_LIGHT0,GL_DIFFUSE,dif);
//ambient light 
float amb[]={0.2,0.2,0.2,1.0};
glLightfv(GL_LIGHT0,GL_AMBIENT,amb);

//http://www.youtube.com/user/thecplusplusguy
//load animation main.cpp
#include "functions.h"
#include "objloader.h"
#include "text.h"
float angle=0.0;

int cube;
objloader obj;
bool mousein=false;
coordinate spherecenter(0.0,0.0,0.0);
coordinate raystart(0.0,0.0,0.0);
text* tex;
std::vector<unsigned int> frames;
int curframe=0;
void init()
{
	glClearColor(0.5,0.5,0.5,1.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45,640.0/480.0,1.0,500.0);
	glMatrixMode(GL_MODELVIEW);
	glEnable(GL_DEPTH_TEST);
	cube=obj.load("test10.obj");
	std::vector<unsigned int> chars;
	char tmp[40];
	for(int i=0;i<26;i++)
	{
		sprintf(tmp,"font/%d.obj",i);
		unsigned int tmp2=obj.load(tmp);
		chars.push_back(tmp2);
	}
	tex=new text(0.9,0.8,chars);
//	cube=loadObject("test.obj");
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	float col[]={1.0,1.0,1.0,1.0};
	glLightfv(GL_LIGHT0,GL_DIFFUSE,col);
	initskybox();
	loadAnimation(frames,"anim/anim",250,obj);
}

coordinate p1(-5.0,5.0,-5.0);
coordinate p2(5.0,5.0,-5.0);
coordinate p3(5.0,-5.0,-5.0);
coordinate p4(-5.0,-5.0,-5.0);
/*

*/

void display()
{
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	Control(0.2,0.2,mousein);
	drawSkybox(50.0);
	UpdateCamera();
	float pos[]={-1.0,1.0,-2.0,1.0};
	glLightfv(GL_LIGHT0,GL_POSITION,pos);
//	glTranslatef(0.0,0.0,-4.0);
//	glRotatef(angle,1,1,1);
	glDisable(GL_LIGHTING);
//	if(raysphere(spherecenter.x,spherecenter.y,spherecenter.z,0.0,0.0,1.0,raystart.x, raystart.y,raystart.z,1.0))
	if(rayplane(0.0,0.0,1.0,raystart.x,raystart.y,raystart.z,0.0,0.0,-1.0,p1,p2,p3,p4))
		glColor3f(1.0,0.0,0.0);
	else
		glColor3f(1.0,1.0,1.0);
	//xs+t*xd
	glBegin(GL_LINES);
		glVertex3f(raystart.x,raystart.y,raystart.z);
		glVertex3f(raystart.x+100*0,raystart.y+100*0,raystart.z+100*-1);
	glEnd();
	glBegin(GL_QUADS);
		glVertex3f(-5.0,5.0,-5.0);
		glVertex3f(5.0,5.0,-5.0);
		glVertex3f(5.0,-5.0,-5.0);
		glVertex3f(-5.0,-5.0,-5.0);
		glColor3f(0,0,0);
		glVertex3f(-10.0,0.0,-10.0);
		glVertex3f(-10.0,-5.0,10.0);
		glVertex3f(10.0,-5.0,10.0);
		glVertex3f(10.0,0.0,-10.0);
	glEnd();
	glEnable(GL_LIGHTING);
	glCallList(cube);
	tex->drawText(coordinate(10,0,0),coordinate(angle,0,0),"HELLO\nWORLD\nFROM\nOPENGL");
	glTranslatef(-20,0,0);
	glCallList(frames[curframe]);
	curframe++;
	if(curframe>249)
		curframe=0;
	std::cout << curframe << std::endl;
	glColor3f(1.0,1.0,1.0);
}

                coordinate p5(-10.0,0,-10.0);
                coordinate p6(-10.0,-5.0,10.0);
                coordinate p7(10.0,-5.0,10.0);
                coordinate p8(10.0,0,-10.0);

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Surface* screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE|SDL_OPENGL);
	bool running=true;
	Uint32 start;
	SDL_Event event;
	init();
	bool b[4]={0,0,0,0};
	while(running)
	{
		start=SDL_GetTicks();
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
					running=false;
					break;
				case SDL_MOUSEBUTTONDOWN:
					mousein=true;
					SDL_ShowCursor(SDL_DISABLE);
					break;
				case SDL_KEYDOWN:
					if(event.key.keysym.sym==SDLK_p)
					{
						mousein=false;
						SDL_ShowCursor(SDL_ENABLE);
						break;
					}
					if(event.key.keysym.sym==SDLK_ESCAPE)
					{
						running=false;
						break;
					}	
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							b[0]=1;
							break;

						case SDLK_LEFT:
							b[1]=1;
							break;

						case SDLK_DOWN:
							b[2]=1;
							break;

						case SDLK_RIGHT:
							b[3]=1;
							break;
					}
					break;				
				case SDL_KEYUP:
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							b[0]=0;
							break;

						case SDLK_LEFT:
							b[1]=0;
							break;

						case SDLK_DOWN:
							b[2]=0;
							break;

						case SDLK_RIGHT:
							b[3]=0;
							break;
					}
					break;						
			}
		}
		if(b[0])
			raystart.y+=0.3;
		if(b[1])
			raystart.x-=0.3;
		if(b[2])
			raystart.y-=0.3;
		if(b[3])
			raystart.x+=0.3;
		display();
		SDL_GL_SwapBuffers();
		angle+=0.5;
		if(angle>360)
			angle-=360;
		coordinate cameraPos=camPos();
		if(spheresphere(cameraPos,2.0,coordinate(0,0,0),1.0))
			std::cout << "collision\n";
		sphereplane(cameraPos,coordinate(0,0,1),p1,p2,p3,p4,2.0);
		sphereplane(cameraPos,coordinate(0,0.9701425,0.242535625),p5,p6,p7,p8,2.0);
		moveTo(cameraPos);
		if(1000/30>(SDL_GetTicks()-start))
			SDL_Delay(1000/30-(SDL_GetTicks()-start));
	}
	SDL_Quit();
	killskybox();
	delete tex;
	return 0;	
}

//http://www.youtube.com/user/thecplusplusguy
//watch the video for explonation
//ray-sphere and ray-plane collision detection.
//if you find a bug, let me know
#include "functions.h"
#include "objloader.h"

float angle=0.0;

int cube;
objloader obj;
bool mousein=false;
coordinate spherecenter(0.0,0.0,0.0);
coordinate raystart(0.0,0.0,0.0);
void init()
{
	glClearColor(0.5,0.5,0.5,1.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45,640.0/480.0,1.0,500.0);
	glMatrixMode(GL_MODELVIEW);
	glEnable(GL_DEPTH_TEST);
	cube=obj.load("test10.obj");
//	cube=loadObject("test.obj");
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	float col[]={1.0,1.0,1.0,1.0};
	glLightfv(GL_LIGHT0,GL_DIFFUSE,col);
	initskybox();
}

coordinate p1(-5.0,5.0,-5.0);
coordinate p2(5.0,5.0,-5.0);
coordinate p3(5.0,-5.0,-5.0);
coordinate p4(-5.0,-5.0,-5.0);
/*

*/

void display()
{
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	Control(0.2,0.2,mousein);
	drawSkybox(50.0);
	UpdateCamera();
	float pos[]={-1.0,1.0,-2.0,1.0};
	glLightfv(GL_LIGHT0,GL_POSITION,pos);
//	glTranslatef(0.0,0.0,-4.0);
//	glRotatef(angle,1,1,1);
	glDisable(GL_LIGHTING);
//	if(raysphere(spherecenter.x,spherecenter.y,spherecenter.z,0.0,0.0,1.0,raystart.x, raystart.y,raystart.z,1.0))
	if(rayplane(0.0,0.0,1.0,raystart.x,raystart.y,raystart.z,0.0,0.0,-1.0,p1,p2,p3,p4))
		glColor3f(1.0,0.0,0.0);
	else
		glColor3f(1.0,1.0,1.0);
	//xs+t*xd
	glBegin(GL_LINES);
		glVertex3f(raystart.x,raystart.y,raystart.z);
		glVertex3f(raystart.x+100*0,raystart.y+100*0,raystart.z+100*-1);
	glEnd();
	glBegin(GL_QUADS);
		glVertex3f(-5.0,5.0,-5.0);
		glVertex3f(5.0,5.0,-5.0);
		glVertex3f(5.0,-5.0,-5.0);
		glVertex3f(-5.0,-5.0,-5.0);
	glEnd();
	glEnable(GL_LIGHTING);
	glCallList(cube);
	glColor3f(1.0,1.0,1.0);
}

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Surface* screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE|SDL_OPENGL);
	bool running=true;
	Uint32 start;
	SDL_Event event;
	init();
	bool b[4]={0,0,0,0};
	while(running)
	{
		start=SDL_GetTicks();
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
					running=false;
					break;
				case SDL_MOUSEBUTTONDOWN:
					mousein=true;
					SDL_ShowCursor(SDL_DISABLE);
					break;
				case SDL_KEYDOWN:
					if(event.key.keysym.sym==SDLK_p)
					{
						mousein=false;
						SDL_ShowCursor(SDL_ENABLE);
						break;
					}
					if(event.key.keysym.sym==SDLK_ESCAPE)
					{
						running=false;
						break;
					}	
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							b[0]=1;
							break;

						case SDLK_LEFT:
							b[1]=1;
							break;

						case SDLK_DOWN:
							b[2]=1;
							break;

						case SDLK_RIGHT:
							b[3]=1;
							break;
					}
					break;				
				case SDL_KEYUP:
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							b[0]=0;
							break;

						case SDLK_LEFT:
							b[1]=0;
							break;

						case SDLK_DOWN:
							b[2]=0;
							break;

						case SDLK_RIGHT:
							b[3]=0;
							break;
					}
					break;						
			}
		}
		if(b[0])
			raystart.y+=0.3;
		if(b[1])
			raystart.x-=0.3;
		if(b[2])
			raystart.y-=0.3;
		if(b[3])
			raystart.x+=0.3;
		display();
		SDL_GL_SwapBuffers();
		angle+=0.5;
		if(angle>360)
			angle-=360;
		if(1000/30>(SDL_GetTicks()-start))
			SDL_Delay(1000/30-(SDL_GetTicks()-start));
	}
	SDL_Quit();
	killskybox();
	return 0;	
}
华夏公益教科书