mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-18 18:58:27 +00:00
Updated iOS tests and demos for latest SDL linking requirements
This commit is contained in:
parent
e87fbb1aa7
commit
1bd4b7fdf1
38 changed files with 8145 additions and 1 deletions
226
Xcode-iOS/Demos/src/accelerometer.c
Normal file
226
Xcode-iOS/Demos/src/accelerometer.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* accelerometer.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include <math.h>
|
||||
#include "common.h"
|
||||
|
||||
#define DAMPING 0.5f; /* after bouncing off a wall, damping coefficient determines final speed */
|
||||
#define FRICTION 0.0008f /* coefficient of acceleration that opposes direction of motion */
|
||||
#define GRAVITY_CONSTANT 0.004f /* how sensitive the ship is to the accelerometer */
|
||||
|
||||
/* If we aren't on an iPhone, then this definition ought to yield reasonable behavior */
|
||||
#ifndef SDL_IPHONE_MAX_GFORCE
|
||||
#define SDL_IPHONE_MAX_GFORCE 5.0f
|
||||
#endif
|
||||
|
||||
static SDL_Joystick *accelerometer; /* used for controlling the ship */
|
||||
|
||||
static struct
|
||||
{
|
||||
float x, y; /* position of ship */
|
||||
float vx, vy; /* velocity of ship (in pixels per millesecond) */
|
||||
SDL_Rect rect; /* (drawn) position and size of ship */
|
||||
} shipData;
|
||||
|
||||
static SDL_Texture *ship = 0; /* texture for spaceship */
|
||||
static SDL_Texture *space = 0; /* texture for space (background */
|
||||
|
||||
void
|
||||
render(SDL_Renderer *renderer, int w, int h, double deltaTime)
|
||||
{
|
||||
double deltaMilliseconds = deltaTime * 1000;
|
||||
float speed;
|
||||
|
||||
/* get joystick (accelerometer) axis values and normalize them */
|
||||
float ax = SDL_JoystickGetAxis(accelerometer, 0);
|
||||
float ay = SDL_JoystickGetAxis(accelerometer, 1);
|
||||
|
||||
/* ship screen constraints */
|
||||
Uint32 minx = 0.0f;
|
||||
Uint32 maxx = w - shipData.rect.w;
|
||||
Uint32 miny = 0.0f;
|
||||
Uint32 maxy = h - shipData.rect.h;
|
||||
|
||||
#define SINT16_MAX ((float)(0x7FFF))
|
||||
|
||||
/* update velocity from accelerometer
|
||||
the factor SDL_IPHONE_MAX_G_FORCE / SINT16_MAX converts between
|
||||
SDL's units reported from the joytick, and units of g-force, as reported by the accelerometer
|
||||
*/
|
||||
shipData.vx +=
|
||||
ax * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT *
|
||||
deltaMilliseconds;
|
||||
shipData.vy +=
|
||||
ay * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT *
|
||||
deltaMilliseconds;
|
||||
|
||||
speed = sqrt(shipData.vx * shipData.vx + shipData.vy * shipData.vy);
|
||||
|
||||
if (speed > 0) {
|
||||
/* compensate for friction */
|
||||
float dirx = shipData.vx / speed; /* normalized x velocity */
|
||||
float diry = shipData.vy / speed; /* normalized y velocity */
|
||||
|
||||
/* update velocity due to friction */
|
||||
if (speed - FRICTION * deltaMilliseconds > 0) {
|
||||
/* apply friction */
|
||||
shipData.vx -= dirx * FRICTION * deltaMilliseconds;
|
||||
shipData.vy -= diry * FRICTION * deltaMilliseconds;
|
||||
} else {
|
||||
/* applying friction would MORE than stop the ship, so just stop the ship */
|
||||
shipData.vx = 0.0f;
|
||||
shipData.vy = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* update ship location */
|
||||
shipData.x += shipData.vx * deltaMilliseconds;
|
||||
shipData.y += shipData.vy * deltaMilliseconds;
|
||||
|
||||
if (shipData.x > maxx) {
|
||||
shipData.x = maxx;
|
||||
shipData.vx = -shipData.vx * DAMPING;
|
||||
} else if (shipData.x < minx) {
|
||||
shipData.x = minx;
|
||||
shipData.vx = -shipData.vx * DAMPING;
|
||||
}
|
||||
if (shipData.y > maxy) {
|
||||
shipData.y = maxy;
|
||||
shipData.vy = -shipData.vy * DAMPING;
|
||||
} else if (shipData.y < miny) {
|
||||
shipData.y = miny;
|
||||
shipData.vy = -shipData.vy * DAMPING;
|
||||
}
|
||||
|
||||
/* draw the background */
|
||||
SDL_RenderCopy(renderer, space, NULL, NULL);
|
||||
|
||||
/* draw the ship */
|
||||
shipData.rect.x = shipData.x;
|
||||
shipData.rect.y = shipData.y;
|
||||
|
||||
SDL_RenderCopy(renderer, ship, NULL, &shipData.rect);
|
||||
|
||||
/* update screen */
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
initializeTextures(SDL_Renderer *renderer)
|
||||
{
|
||||
|
||||
SDL_Surface *bmp_surface;
|
||||
|
||||
/* load the ship */
|
||||
bmp_surface = SDL_LoadBMP("ship.bmp");
|
||||
if (bmp_surface == NULL) {
|
||||
fatalError("could not ship.bmp");
|
||||
}
|
||||
/* set blue to transparent on the ship */
|
||||
SDL_SetColorKey(bmp_surface, 1,
|
||||
SDL_MapRGB(bmp_surface->format, 0, 0, 255));
|
||||
|
||||
/* create ship texture from surface */
|
||||
ship = SDL_CreateTextureFromSurface(renderer, bmp_surface);
|
||||
if (ship == 0) {
|
||||
fatalError("could not create ship texture");
|
||||
}
|
||||
SDL_SetTextureBlendMode(ship, SDL_BLENDMODE_BLEND);
|
||||
|
||||
/* set the width and height of the ship from the surface dimensions */
|
||||
shipData.rect.w = bmp_surface->w;
|
||||
shipData.rect.h = bmp_surface->h;
|
||||
|
||||
SDL_FreeSurface(bmp_surface);
|
||||
|
||||
/* load the space background */
|
||||
bmp_surface = SDL_LoadBMP("space.bmp");
|
||||
if (bmp_surface == NULL) {
|
||||
fatalError("could not load space.bmp");
|
||||
}
|
||||
/* create space texture from surface */
|
||||
space = SDL_CreateTextureFromSurface(renderer, bmp_surface);
|
||||
if (space == 0) {
|
||||
fatalError("could not create space texture");
|
||||
}
|
||||
SDL_FreeSurface(bmp_surface);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
SDL_Window *window; /* main window */
|
||||
SDL_Renderer *renderer;
|
||||
int done; /* should we clean up and exit? */
|
||||
int w, h;
|
||||
|
||||
/* initialize SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
|
||||
fatalError("Could not initialize SDL");
|
||||
}
|
||||
|
||||
/* create main window and renderer */
|
||||
window = SDL_CreateWindow(NULL, 0, 0, 320, 480, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
renderer = SDL_CreateRenderer(window, 0, 0);
|
||||
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
SDL_RenderSetLogicalSize(renderer, w, h);
|
||||
|
||||
/* print out some info about joysticks and try to open accelerometer for use */
|
||||
printf("There are %d joysticks available\n", SDL_NumJoysticks());
|
||||
printf("Default joystick (index 0) is %s\n", SDL_JoystickName(0));
|
||||
accelerometer = SDL_JoystickOpen(0);
|
||||
if (accelerometer == NULL) {
|
||||
fatalError("Could not open joystick (accelerometer)");
|
||||
}
|
||||
printf("joystick number of axis = %d\n",
|
||||
SDL_JoystickNumAxes(accelerometer));
|
||||
printf("joystick number of hats = %d\n",
|
||||
SDL_JoystickNumHats(accelerometer));
|
||||
printf("joystick number of balls = %d\n",
|
||||
SDL_JoystickNumBalls(accelerometer));
|
||||
printf("joystick number of buttons = %d\n",
|
||||
SDL_JoystickNumButtons(accelerometer));
|
||||
|
||||
/* load graphics */
|
||||
initializeTextures(renderer);
|
||||
|
||||
/* setup ship */
|
||||
shipData.x = (w - shipData.rect.w) / 2;
|
||||
shipData.y = (h - shipData.rect.h) / 2;
|
||||
shipData.vx = 0.0f;
|
||||
shipData.vy = 0.0f;
|
||||
|
||||
done = 0;
|
||||
/* enter main loop */
|
||||
while (!done) {
|
||||
double deltaTime = updateDeltaTime();
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
render(renderer, w, h, deltaTime);
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
/* delete textures */
|
||||
SDL_DestroyTexture(ship);
|
||||
SDL_DestroyTexture(space);
|
||||
|
||||
/* shutdown SDL */
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
56
Xcode-iOS/Demos/src/common.c
Normal file
56
Xcode-iOS/Demos/src/common.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* common.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "SDL.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
Produces a random int x, min <= x <= max
|
||||
following a uniform distribution
|
||||
*/
|
||||
int
|
||||
randomInt(int min, int max)
|
||||
{
|
||||
return min + rand() % (max - min + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
Produces a random float x, min <= x <= max
|
||||
following a uniform distribution
|
||||
*/
|
||||
float
|
||||
randomFloat(float min, float max)
|
||||
{
|
||||
return rand() / (float) RAND_MAX *(max - min) + min;
|
||||
}
|
||||
|
||||
void
|
||||
fatalError(const char *string)
|
||||
{
|
||||
printf("%s: %s\n", string, SDL_GetError());
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, string, SDL_GetError(), NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static Uint64 prevTime = 0;
|
||||
|
||||
double
|
||||
updateDeltaTime(void)
|
||||
{
|
||||
Uint64 curTime;
|
||||
double deltaTime;
|
||||
|
||||
if (prevTime == 0) {
|
||||
prevTime = SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
curTime = SDL_GetPerformanceCounter();
|
||||
deltaTime = (double) (curTime - prevTime) / (double) SDL_GetPerformanceFrequency();
|
||||
prevTime = curTime;
|
||||
|
||||
return deltaTime;
|
||||
}
|
10
Xcode-iOS/Demos/src/common.h
Normal file
10
Xcode-iOS/Demos/src/common.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* common.h
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
extern int randomInt(int min, int max);
|
||||
extern float randomFloat(float min, float max);
|
||||
extern void fatalError(const char *string);
|
||||
extern double updateDeltaTime(void);
|
474
Xcode-iOS/Demos/src/fireworks.c
Normal file
474
Xcode-iOS/Demos/src/fireworks.c
Normal file
|
@ -0,0 +1,474 @@
|
|||
/*
|
||||
* fireworks.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_opengles.h"
|
||||
#include "common.h"
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#define ACCEL 0.0001f /* acceleration due to gravity, units in pixels per millesecond squared */
|
||||
#define WIND_RESISTANCE 0.00005f /* acceleration per unit velocity due to wind resistance */
|
||||
#define MAX_PARTICLES 2000 /* maximum number of particles displayed at once */
|
||||
|
||||
static GLuint particleTextureID; /* OpenGL particle texture id */
|
||||
static SDL_bool pointSizeExtensionSupported; /* is GL_OES_point_size_array supported ? */
|
||||
static float pointSizeScale;
|
||||
/*
|
||||
used to describe what type of particle a given struct particle is.
|
||||
emitter - this particle flies up, shooting off trail particles, then finally explodes into dust particles.
|
||||
trail - shoots off, following emitter particle
|
||||
dust - radiates outwards from emitter explosion
|
||||
*/
|
||||
enum particleType
|
||||
{
|
||||
emitter = 0,
|
||||
trail,
|
||||
dust
|
||||
};
|
||||
/*
|
||||
struct particle is used to describe each particle displayed on screen
|
||||
*/
|
||||
struct particle
|
||||
{
|
||||
GLfloat x; /* x position of particle */
|
||||
GLfloat y; /* y position of particle */
|
||||
GLubyte color[4]; /* rgba color of particle */
|
||||
GLfloat size; /* size of particle in pixels */
|
||||
GLfloat xvel; /* x velocity of particle in pixels per milesecond */
|
||||
GLfloat yvel; /* y velocity of particle in pixels per millescond */
|
||||
int isActive; /* if not active, then particle is overwritten */
|
||||
enum particleType type; /* see enum particleType */
|
||||
} particles[MAX_PARTICLES]; /* this array holds all our particles */
|
||||
|
||||
static int num_active_particles; /* how many members of the particle array are actually being drawn / animated? */
|
||||
static int screen_w, screen_h;
|
||||
|
||||
/* function declarations */
|
||||
void spawnTrailFromEmitter(struct particle *emitter);
|
||||
void spawnEmitterParticle(GLfloat x, GLfloat y);
|
||||
void explodeEmitter(struct particle *emitter);
|
||||
void initializeParticles(void);
|
||||
void initializeTexture();
|
||||
int nextPowerOfTwo(int x);
|
||||
void drawParticles();
|
||||
void stepParticles(double deltaTime);
|
||||
|
||||
/* helper function (used in texture loading)
|
||||
returns next power of two greater than or equal to x
|
||||
*/
|
||||
int
|
||||
nextPowerOfTwo(int x)
|
||||
{
|
||||
int val = 1;
|
||||
while (val < x) {
|
||||
val *= 2;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
steps each active particle by timestep deltaTime
|
||||
*/
|
||||
void
|
||||
stepParticles(double deltaTime)
|
||||
{
|
||||
float deltaMilliseconds = deltaTime * 1000;
|
||||
int i;
|
||||
struct particle *slot = particles;
|
||||
struct particle *curr = particles;
|
||||
for (i = 0; i < num_active_particles; i++) {
|
||||
/* is the particle actually active, or is it marked for deletion? */
|
||||
if (curr->isActive) {
|
||||
/* is the particle off the screen? */
|
||||
if (curr->y > screen_h)
|
||||
curr->isActive = 0;
|
||||
else if (curr->y < 0)
|
||||
curr->isActive = 0;
|
||||
if (curr->x > screen_w)
|
||||
curr->isActive = 0;
|
||||
else if (curr->x < 0)
|
||||
curr->isActive = 0;
|
||||
|
||||
/* step velocity, then step position */
|
||||
curr->yvel += ACCEL * deltaMilliseconds;
|
||||
curr->xvel += 0.0f;
|
||||
curr->y += curr->yvel * deltaMilliseconds;
|
||||
curr->x += curr->xvel * deltaMilliseconds;
|
||||
|
||||
/* particle behavior */
|
||||
if (curr->type == emitter) {
|
||||
/* if we're an emitter, spawn a trail */
|
||||
spawnTrailFromEmitter(curr);
|
||||
/* if we've reached our peak, explode */
|
||||
if (curr->yvel > 0.0) {
|
||||
explodeEmitter(curr);
|
||||
}
|
||||
} else {
|
||||
float speed =
|
||||
sqrt(curr->xvel * curr->xvel + curr->yvel * curr->yvel);
|
||||
/* if wind resistance is not powerful enough to stop us completely,
|
||||
then apply winde resistance, otherwise just stop us completely */
|
||||
if (WIND_RESISTANCE * deltaMilliseconds < speed) {
|
||||
float normx = curr->xvel / speed;
|
||||
float normy = curr->yvel / speed;
|
||||
curr->xvel -=
|
||||
normx * WIND_RESISTANCE * deltaMilliseconds;
|
||||
curr->yvel -=
|
||||
normy * WIND_RESISTANCE * deltaMilliseconds;
|
||||
} else {
|
||||
curr->xvel = curr->yvel = 0; /* stop particle */
|
||||
}
|
||||
|
||||
if (curr->color[3] <= deltaMilliseconds * 0.1275f) {
|
||||
/* if this next step will cause us to fade out completely
|
||||
then just mark for deletion */
|
||||
curr->isActive = 0;
|
||||
} else {
|
||||
/* otherwise, let's fade a bit more */
|
||||
curr->color[3] -= deltaMilliseconds * 0.1275f;
|
||||
}
|
||||
|
||||
/* if we're a dust particle, shrink our size */
|
||||
if (curr->type == dust)
|
||||
curr->size -= deltaMilliseconds * 0.010f;
|
||||
|
||||
}
|
||||
|
||||
/* if we're still active, pack ourselves in the array next
|
||||
to the last active guy (pack the array tightly) */
|
||||
if (curr->isActive)
|
||||
*(slot++) = *curr;
|
||||
} /* endif (curr->isActive) */
|
||||
curr++;
|
||||
}
|
||||
/* the number of active particles is computed as the difference between
|
||||
old number of active particles, where slot points, and the
|
||||
new size of the array, where particles points */
|
||||
num_active_particles = (int) (slot - particles);
|
||||
}
|
||||
|
||||
/*
|
||||
This draws all the particles shown on screen
|
||||
*/
|
||||
void
|
||||
drawParticles()
|
||||
{
|
||||
|
||||
/* draw the background */
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* set up the position and color pointers */
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(struct particle), particles);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(struct particle),
|
||||
particles[0].color);
|
||||
|
||||
if (pointSizeExtensionSupported) {
|
||||
/* pass in our array of point sizes */
|
||||
glPointSizePointerOES(GL_FLOAT, sizeof(struct particle),
|
||||
&(particles[0].size));
|
||||
}
|
||||
|
||||
/* draw our particles! */
|
||||
glDrawArrays(GL_POINTS, 0, num_active_particles);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This causes an emitter to explode in a circular bloom of dust particles
|
||||
*/
|
||||
void
|
||||
explodeEmitter(struct particle *emitter)
|
||||
{
|
||||
/* first off, we're done with this particle, so turn active off */
|
||||
emitter->isActive = 0;
|
||||
int i;
|
||||
for (i = 0; i < 200; i++) {
|
||||
|
||||
if (num_active_particles >= MAX_PARTICLES)
|
||||
return;
|
||||
|
||||
/* come up with a random angle and speed for new particle */
|
||||
float theta = randomFloat(0, 2.0f * 3.141592);
|
||||
float exponent = 3.0f;
|
||||
float speed = randomFloat(0.00, powf(0.17, exponent));
|
||||
speed = powf(speed, 1.0f / exponent);
|
||||
|
||||
/* select the particle at the end of our array */
|
||||
struct particle *p = &particles[num_active_particles];
|
||||
|
||||
/* set the particles properties */
|
||||
p->xvel = speed * cos(theta);
|
||||
p->yvel = speed * sin(theta);
|
||||
p->x = emitter->x + emitter->xvel;
|
||||
p->y = emitter->y + emitter->yvel;
|
||||
p->isActive = 1;
|
||||
p->type = dust;
|
||||
p->size = 15 * pointSizeScale;
|
||||
/* inherit emitter's color */
|
||||
p->color[0] = emitter->color[0];
|
||||
p->color[1] = emitter->color[1];
|
||||
p->color[2] = emitter->color[2];
|
||||
p->color[3] = 255;
|
||||
/* our array has expanded at the end */
|
||||
num_active_particles++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This spawns a trail particle from an emitter
|
||||
*/
|
||||
void
|
||||
spawnTrailFromEmitter(struct particle *emitter)
|
||||
{
|
||||
|
||||
if (num_active_particles >= MAX_PARTICLES)
|
||||
return;
|
||||
|
||||
/* select the particle at the slot at the end of our array */
|
||||
struct particle *p = &particles[num_active_particles];
|
||||
|
||||
/* set position and velocity to roughly that of the emitter */
|
||||
p->x = emitter->x + randomFloat(-3.0, 3.0);
|
||||
p->y = emitter->y + emitter->size / 2.0f;
|
||||
p->xvel = emitter->xvel + randomFloat(-0.005, 0.005);
|
||||
p->yvel = emitter->yvel + 0.1;
|
||||
|
||||
/* set the color to a random-ish orangy type color */
|
||||
p->color[0] = (0.8f + randomFloat(-0.1, 0.0)) * 255;
|
||||
p->color[1] = (0.4f + randomFloat(-0.1, 0.1)) * 255;
|
||||
p->color[2] = (0.0f + randomFloat(0.0, 0.2)) * 255;
|
||||
p->color[3] = (0.7f) * 255;
|
||||
|
||||
/* set other attributes */
|
||||
p->size = 10 * pointSizeScale;
|
||||
p->type = trail;
|
||||
p->isActive = 1;
|
||||
|
||||
/* our array has expanded at the end */
|
||||
num_active_particles++;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
spawns a new emitter particle at the bottom of the screen
|
||||
destined for the point (x,y).
|
||||
*/
|
||||
void
|
||||
spawnEmitterParticle(GLfloat x, GLfloat y)
|
||||
{
|
||||
|
||||
if (num_active_particles >= MAX_PARTICLES)
|
||||
return;
|
||||
|
||||
/* find particle at endpoint of array */
|
||||
struct particle *p = &particles[num_active_particles];
|
||||
|
||||
/* set the color randomly */
|
||||
switch (rand() % 4) {
|
||||
case 0:
|
||||
p->color[0] = 255;
|
||||
p->color[1] = 100;
|
||||
p->color[2] = 100;
|
||||
break;
|
||||
case 1:
|
||||
p->color[0] = 100;
|
||||
p->color[1] = 255;
|
||||
p->color[2] = 100;
|
||||
break;
|
||||
case 2:
|
||||
p->color[0] = 100;
|
||||
p->color[1] = 100;
|
||||
p->color[2] = 255;
|
||||
break;
|
||||
case 3:
|
||||
p->color[0] = 255;
|
||||
p->color[1] = 150;
|
||||
p->color[2] = 50;
|
||||
break;
|
||||
}
|
||||
p->color[3] = 255;
|
||||
/* set position to (x, screen_h) */
|
||||
p->x = x;
|
||||
p->y = screen_h;
|
||||
/* set velocity so that terminal point is (x,y) */
|
||||
p->xvel = 0;
|
||||
p->yvel = -sqrt(2 * ACCEL * (screen_h - y));
|
||||
/* set other attributes */
|
||||
p->size = 10 * pointSizeScale;
|
||||
p->type = emitter;
|
||||
p->isActive = 1;
|
||||
/* our array has expanded at the end */
|
||||
num_active_particles++;
|
||||
}
|
||||
|
||||
/* just sets the endpoint of the particle array to element zero */
|
||||
void
|
||||
initializeParticles(void)
|
||||
{
|
||||
num_active_particles = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
loads the particle texture
|
||||
*/
|
||||
void
|
||||
initializeTexture()
|
||||
{
|
||||
|
||||
int bpp; /* texture bits per pixel */
|
||||
Uint32 Rmask, Gmask, Bmask, Amask; /* masks for pixel format passed into OpenGL */
|
||||
SDL_Surface *bmp_surface; /* the bmp is loaded here */
|
||||
SDL_Surface *bmp_surface_rgba8888; /* this serves as a destination to convert the BMP
|
||||
to format passed into OpenGL */
|
||||
|
||||
bmp_surface = SDL_LoadBMP("stroke.bmp");
|
||||
if (bmp_surface == NULL) {
|
||||
fatalError("could not load stroke.bmp");
|
||||
}
|
||||
|
||||
/* Grab info about format that will be passed into OpenGL */
|
||||
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &Rmask, &Gmask,
|
||||
&Bmask, &Amask);
|
||||
/* Create surface that will hold pixels passed into OpenGL */
|
||||
bmp_surface_rgba8888 =
|
||||
SDL_CreateRGBSurface(0, bmp_surface->w, bmp_surface->h, bpp, Rmask,
|
||||
Gmask, Bmask, Amask);
|
||||
/* Blit to this surface, effectively converting the format */
|
||||
SDL_BlitSurface(bmp_surface, NULL, bmp_surface_rgba8888, NULL);
|
||||
|
||||
glGenTextures(1, &particleTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, particleTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
nextPowerOfTwo(bmp_surface->w),
|
||||
nextPowerOfTwo(bmp_surface->h),
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
/* this is where we actually pass in the pixel data */
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp_surface->w, bmp_surface->h, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, bmp_surface_rgba8888->pixels);
|
||||
|
||||
/* free bmp surface and converted bmp surface */
|
||||
SDL_FreeSurface(bmp_surface);
|
||||
SDL_FreeSurface(bmp_surface_rgba8888);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
SDL_Window *window; /* main window */
|
||||
SDL_GLContext context;
|
||||
int drawableW, drawableH;
|
||||
int done; /* should we clean up and exit? */
|
||||
|
||||
/* initialize SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
fatalError("Could not initialize SDL");
|
||||
}
|
||||
/* seed the random number generator */
|
||||
srand(time(NULL));
|
||||
/*
|
||||
request some OpenGL parameters
|
||||
that may speed drawing
|
||||
*/
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
|
||||
/* create main window and renderer */
|
||||
window = SDL_CreateWindow(NULL, 0, 0, 320, 480,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
|
||||
/* The window size and drawable size may be different when highdpi is enabled,
|
||||
* due to the increased pixel density of the drawable. */
|
||||
SDL_GetWindowSize(window, &screen_w, &screen_h);
|
||||
SDL_GL_GetDrawableSize(window, &drawableW, &drawableH);
|
||||
|
||||
/* In OpenGL, point sizes are always in pixels. We don't want them looking
|
||||
* tiny on a retina screen. */
|
||||
pointSizeScale = (float) drawableH / (float) screen_h;
|
||||
|
||||
/* load the particle texture */
|
||||
initializeTexture();
|
||||
|
||||
/* check if GL_POINT_SIZE_ARRAY_OES is supported
|
||||
this is used to give each particle its own size
|
||||
*/
|
||||
pointSizeExtensionSupported =
|
||||
SDL_GL_ExtensionSupported("GL_OES_point_size_array");
|
||||
|
||||
/* set up some OpenGL state */
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glViewport(0, 0, drawableW, drawableH);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrthof((GLfloat) 0,
|
||||
(GLfloat) screen_w,
|
||||
(GLfloat) screen_h,
|
||||
(GLfloat) 0, 0.0, 1.0);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glEnable(GL_POINT_SPRITE_OES);
|
||||
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, 1);
|
||||
|
||||
if (pointSizeExtensionSupported) {
|
||||
/* we use this to set the sizes of all the particles */
|
||||
glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
|
||||
} else {
|
||||
/* if extension not available then all particles have size 10 */
|
||||
glPointSize(10 * pointSizeScale);
|
||||
}
|
||||
|
||||
done = 0;
|
||||
/* enter main loop */
|
||||
while (!done) {
|
||||
SDL_Event event;
|
||||
double deltaTime = updateDeltaTime();
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = 1;
|
||||
}
|
||||
if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
int x, y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
spawnEmitterParticle(x, y);
|
||||
}
|
||||
}
|
||||
stepParticles(deltaTime);
|
||||
drawParticles();
|
||||
SDL_GL_SwapWindow(window);
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
/* delete textures */
|
||||
glDeleteTextures(1, &particleTextureID);
|
||||
/* shutdown SDL */
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
180
Xcode-iOS/Demos/src/happy.c
Normal file
180
Xcode-iOS/Demos/src/happy.c
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* happy.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include "common.h"
|
||||
|
||||
#define NUM_HAPPY_FACES 100 /* number of faces to draw */
|
||||
#define HAPPY_FACE_SIZE 32 /* width and height of happyface */
|
||||
|
||||
static SDL_Texture *texture = 0; /* reference to texture holding happyface */
|
||||
|
||||
static struct
|
||||
{
|
||||
float x, y; /* position of happyface */
|
||||
float xvel, yvel; /* velocity of happyface */
|
||||
} faces[NUM_HAPPY_FACES];
|
||||
|
||||
/*
|
||||
Sets initial positions and velocities of happyfaces
|
||||
units of velocity are pixels per millesecond
|
||||
*/
|
||||
void
|
||||
initializeHappyFaces(SDL_Renderer *renderer)
|
||||
{
|
||||
int i;
|
||||
int w;
|
||||
int h;
|
||||
SDL_RenderGetLogicalSize(renderer, &w, &h);
|
||||
|
||||
for (i = 0; i < NUM_HAPPY_FACES; i++) {
|
||||
faces[i].x = randomFloat(0.0f, w - HAPPY_FACE_SIZE);
|
||||
faces[i].y = randomFloat(0.0f, h - HAPPY_FACE_SIZE);
|
||||
faces[i].xvel = randomFloat(-60.0f, 60.0f);
|
||||
faces[i].yvel = randomFloat(-60.0f, 60.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
render(SDL_Renderer *renderer, double deltaTime)
|
||||
{
|
||||
int i;
|
||||
SDL_Rect srcRect;
|
||||
SDL_Rect dstRect;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
SDL_RenderGetLogicalSize(renderer, &w, &h);
|
||||
|
||||
/* setup boundaries for happyface bouncing */
|
||||
int maxx = w - HAPPY_FACE_SIZE;
|
||||
int maxy = h - HAPPY_FACE_SIZE;
|
||||
int minx = 0;
|
||||
int miny = 0;
|
||||
|
||||
/* setup rects for drawing */
|
||||
srcRect.x = 0;
|
||||
srcRect.y = 0;
|
||||
srcRect.w = HAPPY_FACE_SIZE;
|
||||
srcRect.h = HAPPY_FACE_SIZE;
|
||||
dstRect.w = HAPPY_FACE_SIZE;
|
||||
dstRect.h = HAPPY_FACE_SIZE;
|
||||
|
||||
/* fill background in with black */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
/*
|
||||
loop through all the happy faces:
|
||||
- update position
|
||||
- update velocity (if boundary is hit)
|
||||
- draw
|
||||
*/
|
||||
for (i = 0; i < NUM_HAPPY_FACES; i++) {
|
||||
faces[i].x += faces[i].xvel * deltaTime;
|
||||
faces[i].y += faces[i].yvel * deltaTime;
|
||||
if (faces[i].x > maxx) {
|
||||
faces[i].x = maxx;
|
||||
faces[i].xvel = -faces[i].xvel;
|
||||
} else if (faces[i].y > maxy) {
|
||||
faces[i].y = maxy;
|
||||
faces[i].yvel = -faces[i].yvel;
|
||||
}
|
||||
if (faces[i].x < minx) {
|
||||
faces[i].x = minx;
|
||||
faces[i].xvel = -faces[i].xvel;
|
||||
} else if (faces[i].y < miny) {
|
||||
faces[i].y = miny;
|
||||
faces[i].yvel = -faces[i].yvel;
|
||||
}
|
||||
dstRect.x = faces[i].x;
|
||||
dstRect.y = faces[i].y;
|
||||
SDL_RenderCopy(renderer, texture, &srcRect, &dstRect);
|
||||
}
|
||||
/* update screen */
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
loads the happyface graphic into a texture
|
||||
*/
|
||||
void
|
||||
initializeTexture(SDL_Renderer *renderer)
|
||||
{
|
||||
SDL_Surface *bmp_surface;
|
||||
/* load the bmp */
|
||||
bmp_surface = SDL_LoadBMP("icon.bmp");
|
||||
if (bmp_surface == NULL) {
|
||||
fatalError("could not load bmp");
|
||||
}
|
||||
/* set white to transparent on the happyface */
|
||||
SDL_SetColorKey(bmp_surface, 1,
|
||||
SDL_MapRGB(bmp_surface->format, 255, 255, 255));
|
||||
|
||||
/* convert RGBA surface to texture */
|
||||
texture = SDL_CreateTextureFromSurface(renderer, bmp_surface);
|
||||
if (texture == 0) {
|
||||
fatalError("could not create texture");
|
||||
}
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
|
||||
/* free up allocated memory */
|
||||
SDL_FreeSurface(bmp_surface);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
int done;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
/* initialize SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
fatalError("Could not initialize SDL");
|
||||
}
|
||||
|
||||
/* The specified window size doesn't matter - except for its aspect ratio,
|
||||
* which determines whether the window is in portrait or landscape on iOS
|
||||
* (if SDL_WINDOW_RESIZABLE isn't specified). */
|
||||
window = SDL_CreateWindow(NULL, 0, 0, 320, 480, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
|
||||
initializeTexture(renderer);
|
||||
initializeHappyFaces(renderer);
|
||||
|
||||
|
||||
/* main loop */
|
||||
done = 0;
|
||||
while (!done) {
|
||||
SDL_Event event;
|
||||
double deltaTime = updateDeltaTime();
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
render(renderer, deltaTime);
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
SDL_DestroyTexture(texture);
|
||||
/* shutdown SDL */
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
301
Xcode-iOS/Demos/src/keyboard.c
Normal file
301
Xcode-iOS/Demos/src/keyboard.c
Normal file
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* keyboard.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include "common.h"
|
||||
|
||||
#define TEST_INPUT_RECT
|
||||
|
||||
#define GLYPH_SIZE_IMAGE 16 /* size of glyphs (characters) in the bitmap font file */
|
||||
#define GLYPH_SIZE_SCREEN 32 /* size of glyphs (characters) as shown on the screen */
|
||||
|
||||
#define MAX_CHARS 1024
|
||||
|
||||
static SDL_Texture *texture; /* texture where we'll hold our font */
|
||||
|
||||
static SDL_Renderer *renderer;
|
||||
static int numChars = 0; /* number of characters we've typed so far */
|
||||
static SDL_Color bg_color = { 50, 50, 100, 255 }; /* color of background */
|
||||
|
||||
static int glyphs[MAX_CHARS];
|
||||
|
||||
/* this structure maps a scancode to an index in our bitmap font.
|
||||
it also contains data about under which modifiers the mapping is valid
|
||||
(for example, we don't want shift + 1 to produce the character '1',
|
||||
but rather the character '!')
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
SDL_Scancode scancode; /* scancode of the key we want to map */
|
||||
int allow_no_mod; /* is the map valid if the key has no modifiers? */
|
||||
SDL_Keymod mod; /* what modifiers are allowed for the mapping */
|
||||
int index; /* what index in the font does the scancode map to */
|
||||
} fontMapping;
|
||||
|
||||
#define TABLE_SIZE 51 /* size of our table which maps keys and modifiers to font indices */
|
||||
|
||||
/* Below is the table that defines the mapping between scancodes and modifiers to indices in the
|
||||
bitmap font. As an example, then line '{ SDL_SCANCODE_A, 1, KMOD_SHIFT, 33 }' means, map
|
||||
the key A (which has scancode SDL_SCANCODE_A) to index 33 in the font (which is a picture of an A),
|
||||
The '1' means that the mapping is valid even if there are no modifiers, and KMOD_SHIFT means the
|
||||
mapping is also valid if the user is holding shift.
|
||||
*/
|
||||
fontMapping map[TABLE_SIZE] = {
|
||||
|
||||
{SDL_SCANCODE_A, 1, KMOD_SHIFT, 33}, /* A */
|
||||
{SDL_SCANCODE_B, 1, KMOD_SHIFT, 34}, /* B */
|
||||
{SDL_SCANCODE_C, 1, KMOD_SHIFT, 35}, /* C */
|
||||
{SDL_SCANCODE_D, 1, KMOD_SHIFT, 36}, /* D */
|
||||
{SDL_SCANCODE_E, 1, KMOD_SHIFT, 37}, /* E */
|
||||
{SDL_SCANCODE_F, 1, KMOD_SHIFT, 38}, /* F */
|
||||
{SDL_SCANCODE_G, 1, KMOD_SHIFT, 39}, /* G */
|
||||
{SDL_SCANCODE_H, 1, KMOD_SHIFT, 40}, /* H */
|
||||
{SDL_SCANCODE_I, 1, KMOD_SHIFT, 41}, /* I */
|
||||
{SDL_SCANCODE_J, 1, KMOD_SHIFT, 42}, /* J */
|
||||
{SDL_SCANCODE_K, 1, KMOD_SHIFT, 43}, /* K */
|
||||
{SDL_SCANCODE_L, 1, KMOD_SHIFT, 44}, /* L */
|
||||
{SDL_SCANCODE_M, 1, KMOD_SHIFT, 45}, /* M */
|
||||
{SDL_SCANCODE_N, 1, KMOD_SHIFT, 46}, /* N */
|
||||
{SDL_SCANCODE_O, 1, KMOD_SHIFT, 47}, /* O */
|
||||
{SDL_SCANCODE_P, 1, KMOD_SHIFT, 48}, /* P */
|
||||
{SDL_SCANCODE_Q, 1, KMOD_SHIFT, 49}, /* Q */
|
||||
{SDL_SCANCODE_R, 1, KMOD_SHIFT, 50}, /* R */
|
||||
{SDL_SCANCODE_S, 1, KMOD_SHIFT, 51}, /* S */
|
||||
{SDL_SCANCODE_T, 1, KMOD_SHIFT, 52}, /* T */
|
||||
{SDL_SCANCODE_U, 1, KMOD_SHIFT, 53}, /* U */
|
||||
{SDL_SCANCODE_V, 1, KMOD_SHIFT, 54}, /* V */
|
||||
{SDL_SCANCODE_W, 1, KMOD_SHIFT, 55}, /* W */
|
||||
{SDL_SCANCODE_X, 1, KMOD_SHIFT, 56}, /* X */
|
||||
{SDL_SCANCODE_Y, 1, KMOD_SHIFT, 57}, /* Y */
|
||||
{SDL_SCANCODE_Z, 1, KMOD_SHIFT, 58}, /* Z */
|
||||
{SDL_SCANCODE_0, 1, 0, 16}, /* 0 */
|
||||
{SDL_SCANCODE_1, 1, 0, 17}, /* 1 */
|
||||
{SDL_SCANCODE_2, 1, 0, 18}, /* 2 */
|
||||
{SDL_SCANCODE_3, 1, 0, 19}, /* 3 */
|
||||
{SDL_SCANCODE_4, 1, 0, 20}, /* 4 */
|
||||
{SDL_SCANCODE_5, 1, 0, 21}, /* 5 */
|
||||
{SDL_SCANCODE_6, 1, 0, 22}, /* 6 */
|
||||
{SDL_SCANCODE_7, 1, 0, 23}, /* 7 */
|
||||
{SDL_SCANCODE_8, 1, 0, 24}, /* 8 */
|
||||
{SDL_SCANCODE_9, 1, 0, 25}, /* 9 */
|
||||
{SDL_SCANCODE_SPACE, 1, 0, 0}, /* ' ' */
|
||||
{SDL_SCANCODE_1, 0, KMOD_SHIFT, 1}, /* ! */
|
||||
{SDL_SCANCODE_SLASH, 0, KMOD_SHIFT, 31}, /* ? */
|
||||
{SDL_SCANCODE_SLASH, 1, 0, 15}, /* / */
|
||||
{SDL_SCANCODE_COMMA, 1, 0, 12}, /* , */
|
||||
{SDL_SCANCODE_SEMICOLON, 1, 0, 27}, /* ; */
|
||||
{SDL_SCANCODE_SEMICOLON, 0, KMOD_SHIFT, 26}, /* : */
|
||||
{SDL_SCANCODE_PERIOD, 1, 0, 14}, /* . */
|
||||
{SDL_SCANCODE_MINUS, 1, 0, 13}, /* - */
|
||||
{SDL_SCANCODE_EQUALS, 0, KMOD_SHIFT, 11}, /* = */
|
||||
{SDL_SCANCODE_APOSTROPHE, 1, 0, 7}, /* ' */
|
||||
{SDL_SCANCODE_APOSTROPHE, 0, KMOD_SHIFT, 2}, /* " */
|
||||
{SDL_SCANCODE_5, 0, KMOD_SHIFT, 5}, /* % */
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
This function maps an SDL_KeySym to an index in the bitmap font.
|
||||
It does so by scanning through the font mapping table one entry
|
||||
at a time.
|
||||
|
||||
If a match is found (scancode and allowed modifiers), the proper
|
||||
index is returned.
|
||||
|
||||
If there is no entry for the key, -1 is returned
|
||||
*/
|
||||
int
|
||||
keyToGlyphIndex(SDL_Keysym key)
|
||||
{
|
||||
int i, index = -1;
|
||||
for (i = 0; i < TABLE_SIZE; i++) {
|
||||
fontMapping compare = map[i];
|
||||
if (key.scancode == compare.scancode) {
|
||||
/* if this entry is valid with no key mod and we have no keymod, or if
|
||||
the key's modifiers are allowed modifiers for that mapping */
|
||||
if ((compare.allow_no_mod && key.mod == 0)
|
||||
|| (key.mod & compare.mod)) {
|
||||
index = compare.index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
This function returns and x,y position for a given character number.
|
||||
It is used for positioning each character of text
|
||||
*/
|
||||
void
|
||||
getPositionForCharNumber(int n, int *x, int *y)
|
||||
{
|
||||
int renderW, renderH;
|
||||
SDL_RenderGetLogicalSize(renderer, &renderW, &renderH);
|
||||
|
||||
int x_padding = 16; /* padding space on left and right side of screen */
|
||||
int y_padding = 32; /* padding space at top of screen */
|
||||
/* figure out the number of characters that can fit horizontally across the screen */
|
||||
int max_x_chars = (renderW - 2 * x_padding) / GLYPH_SIZE_SCREEN;
|
||||
int line_separation = 5; /* pixels between each line */
|
||||
*x = (n % max_x_chars) * GLYPH_SIZE_SCREEN + x_padding;
|
||||
#ifdef TEST_INPUT_RECT
|
||||
*y = renderH - GLYPH_SIZE_SCREEN;
|
||||
#else
|
||||
*y = (n / max_x_chars) * (GLYPH_SIZE_SCREEN + line_separation) + y_padding;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
drawGlyph(int glyph, int positionIndex)
|
||||
{
|
||||
int x, y;
|
||||
getPositionForCharNumber(positionIndex, &x, &y);
|
||||
SDL_Rect srcRect = { GLYPH_SIZE_IMAGE * glyph, 0, GLYPH_SIZE_IMAGE, GLYPH_SIZE_IMAGE };
|
||||
SDL_Rect dstRect = { x, y, GLYPH_SIZE_SCREEN, GLYPH_SIZE_SCREEN };
|
||||
SDL_RenderCopy(renderer, texture, &srcRect, &dstRect);
|
||||
}
|
||||
|
||||
/* this function loads our font into an SDL_Texture and returns the SDL_Texture */
|
||||
SDL_Texture*
|
||||
loadFont(void)
|
||||
{
|
||||
SDL_Surface *surface = SDL_LoadBMP("kromasky_16x16.bmp");
|
||||
|
||||
if (!surface) {
|
||||
printf("Error loading bitmap: %s\n", SDL_GetError());
|
||||
return 0;
|
||||
} else {
|
||||
/* set the transparent color for the bitmap font (hot pink) */
|
||||
SDL_SetColorKey(surface, 1, SDL_MapRGB(surface->format, 238, 0, 252));
|
||||
/* now we convert the surface to our desired pixel format */
|
||||
int format = SDL_PIXELFORMAT_ABGR8888; /* desired texture format */
|
||||
Uint32 Rmask, Gmask, Bmask, Amask; /* masks for desired format */
|
||||
int bpp; /* bits per pixel for desired format */
|
||||
SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask,
|
||||
&Amask);
|
||||
SDL_Surface *converted =
|
||||
SDL_CreateRGBSurface(0, surface->w, surface->h, bpp, Rmask, Gmask,
|
||||
Bmask, Amask);
|
||||
SDL_BlitSurface(surface, NULL, converted, NULL);
|
||||
/* create our texture */
|
||||
texture = SDL_CreateTextureFromSurface(renderer, converted);
|
||||
if (texture == 0) {
|
||||
printf("texture creation failed: %s\n", SDL_GetError());
|
||||
} else {
|
||||
/* set blend mode for our texture */
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_FreeSurface(converted);
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw()
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer, bg_color.r, bg_color.g, bg_color.b, bg_color.a);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
for (int i = 0; i < numChars; i++) {
|
||||
drawGlyph(glyphs[i], i);
|
||||
}
|
||||
|
||||
drawGlyph(29, numChars); /* cursor is at index 29 in the bitmap font */
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
SDL_Window *window;
|
||||
SDL_Event event; /* last event received */
|
||||
SDL_Scancode scancode; /* scancode of last key we pushed */
|
||||
int width;
|
||||
int height;
|
||||
int done;
|
||||
SDL_Rect textrect;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
printf("Error initializing SDL: %s", SDL_GetError());
|
||||
}
|
||||
/* create window */
|
||||
window = SDL_CreateWindow("iOS keyboard test", 0, 0, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
/* create renderer */
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
|
||||
/* load up our font */
|
||||
loadFont();
|
||||
|
||||
/* Show onscreen keyboard */
|
||||
#ifdef TEST_INPUT_RECT
|
||||
textrect.x = 0;
|
||||
textrect.y = height - GLYPH_SIZE_IMAGE;
|
||||
textrect.w = width;
|
||||
textrect.h = GLYPH_SIZE_IMAGE;
|
||||
SDL_SetTextInputRect(&textrect);
|
||||
#endif
|
||||
SDL_StartTextInput();
|
||||
|
||||
done = 0;
|
||||
while (!done) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
done = 1;
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
width = event.window.data1;
|
||||
height = event.window.data2;
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
#ifdef TEST_INPUT_RECT
|
||||
textrect.x = 0;
|
||||
textrect.y = height - GLYPH_SIZE_IMAGE;
|
||||
textrect.w = width;
|
||||
textrect.h = GLYPH_SIZE_IMAGE;
|
||||
SDL_SetTextInputRect(&textrect);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_BACKSPACE) {
|
||||
if (numChars > 0) {
|
||||
numChars--;
|
||||
}
|
||||
} else if (numChars + 1 < MAX_CHARS) {
|
||||
int index = keyToGlyphIndex(event.key.keysym);
|
||||
if (index >= 0) {
|
||||
glyphs[numChars++] = index;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
/* mouse up toggles onscreen keyboard visibility */
|
||||
if (SDL_IsTextInputActive()) {
|
||||
SDL_StopTextInput();
|
||||
} else {
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
||||
SDL_Delay(15);
|
||||
}
|
||||
|
||||
SDL_DestroyTexture(texture);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
344
Xcode-iOS/Demos/src/mixer.c
Normal file
344
Xcode-iOS/Demos/src/mixer.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* mixer.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include "common.h"
|
||||
|
||||
#define NUM_CHANNELS 8 /* max number of sounds we can play at once */
|
||||
#define NUM_DRUMS 4 /* number of drums in our set */
|
||||
|
||||
static struct
|
||||
{
|
||||
SDL_Rect rect; /* where the button is drawn */
|
||||
SDL_Color upColor; /* color when button is not active */
|
||||
SDL_Color downColor; /* color when button is active */
|
||||
int isPressed; /* is the button being pressed ? */
|
||||
int touchIndex; /* what mouse (touch) index pressed the button ? */
|
||||
} buttons[NUM_DRUMS];
|
||||
|
||||
struct sound
|
||||
{
|
||||
Uint8 *buffer; /* audio buffer for sound file */
|
||||
Uint32 length; /* length of the buffer (in bytes) */
|
||||
};
|
||||
|
||||
/* this array holds the audio for the drum noises */
|
||||
static struct sound drums[NUM_DRUMS];
|
||||
|
||||
/* function declarations */
|
||||
void handleMouseButtonDown(SDL_Event * event);
|
||||
void handleMouseButtonUp(SDL_Event * event);
|
||||
int playSound(struct sound *);
|
||||
void initializeButtons(SDL_Renderer *);
|
||||
void audioCallback(void *userdata, Uint8 * stream, int len);
|
||||
void loadSound(const char *file, struct sound *s);
|
||||
|
||||
struct
|
||||
{
|
||||
/* channel array holds information about currently playing sounds */
|
||||
struct
|
||||
{
|
||||
Uint8 *position; /* what is the current position in the buffer of this sound ? */
|
||||
Uint32 remaining; /* how many bytes remaining before we're done playing the sound ? */
|
||||
Uint32 timestamp; /* when did this sound start playing ? */
|
||||
} channels[NUM_CHANNELS];
|
||||
SDL_AudioSpec outputSpec; /* what audio format are we using for output? */
|
||||
int numSoundsPlaying; /* how many sounds are currently playing */
|
||||
} mixer;
|
||||
|
||||
/* sets up the buttons (color, position, state) */
|
||||
void
|
||||
initializeButtons(SDL_Renderer *renderer)
|
||||
{
|
||||
int i;
|
||||
int spacing = 10; /* gap between drum buttons */
|
||||
SDL_Rect buttonRect; /* keeps track of where to position drum */
|
||||
SDL_Color upColor = { 86, 86, 140, 255 }; /* color of drum when not pressed */
|
||||
SDL_Color downColor = { 191, 191, 221, 255 }; /* color of drum when pressed */
|
||||
int renderW, renderH;
|
||||
|
||||
SDL_RenderGetLogicalSize(renderer, &renderW, &renderH);
|
||||
|
||||
buttonRect.x = spacing;
|
||||
buttonRect.y = spacing;
|
||||
buttonRect.w = renderW - 2 * spacing;
|
||||
buttonRect.h = (renderH - (NUM_DRUMS + 1) * spacing) / NUM_DRUMS;
|
||||
|
||||
/* setup each button */
|
||||
for (i = 0; i < NUM_DRUMS; i++) {
|
||||
|
||||
buttons[i].rect = buttonRect;
|
||||
buttons[i].isPressed = 0;
|
||||
buttons[i].upColor = upColor;
|
||||
buttons[i].downColor = downColor;
|
||||
|
||||
buttonRect.y += spacing + buttonRect.h; /* setup y coordinate for next drum */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
loads a wav file (stored in 'file'), converts it to the mixer's output format,
|
||||
and stores the resulting buffer and length in the sound structure
|
||||
*/
|
||||
void
|
||||
loadSound(const char *file, struct sound *s)
|
||||
{
|
||||
SDL_AudioSpec spec; /* the audio format of the .wav file */
|
||||
SDL_AudioCVT cvt; /* used to convert .wav to output format when formats differ */
|
||||
int result;
|
||||
if (SDL_LoadWAV(file, &spec, &s->buffer, &s->length) == NULL) {
|
||||
fatalError("could not load .wav");
|
||||
}
|
||||
/* build the audio converter */
|
||||
result = SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq,
|
||||
mixer.outputSpec.format,
|
||||
mixer.outputSpec.channels,
|
||||
mixer.outputSpec.freq);
|
||||
if (result == -1) {
|
||||
fatalError("could not build audio CVT");
|
||||
} else if (result != 0) {
|
||||
/*
|
||||
this happens when the .wav format differs from the output format.
|
||||
we convert the .wav buffer here
|
||||
*/
|
||||
cvt.buf = (Uint8 *) SDL_malloc(s->length * cvt.len_mult); /* allocate conversion buffer */
|
||||
cvt.len = s->length; /* set conversion buffer length */
|
||||
SDL_memcpy(cvt.buf, s->buffer, s->length); /* copy sound to conversion buffer */
|
||||
if (SDL_ConvertAudio(&cvt) == -1) { /* convert the sound */
|
||||
fatalError("could not convert .wav");
|
||||
}
|
||||
SDL_free(s->buffer); /* free the original (unconverted) buffer */
|
||||
s->buffer = cvt.buf; /* point sound buffer to converted buffer */
|
||||
s->length = cvt.len_cvt; /* set sound buffer's new length */
|
||||
}
|
||||
}
|
||||
|
||||
/* called from main event loop */
|
||||
void
|
||||
handleMouseButtonDown(SDL_Event * event)
|
||||
{
|
||||
|
||||
int x, y, mouseIndex, i, drumIndex;
|
||||
|
||||
mouseIndex = 0;
|
||||
drumIndex = -1;
|
||||
|
||||
SDL_GetMouseState(&x, &y);
|
||||
/* check if we hit any of the drum buttons */
|
||||
for (i = 0; i < NUM_DRUMS; i++) {
|
||||
if (x >= buttons[i].rect.x
|
||||
&& x < buttons[i].rect.x + buttons[i].rect.w
|
||||
&& y >= buttons[i].rect.y
|
||||
&& y < buttons[i].rect.y + buttons[i].rect.h) {
|
||||
drumIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (drumIndex != -1) {
|
||||
/* if we hit a button */
|
||||
buttons[drumIndex].touchIndex = mouseIndex;
|
||||
buttons[drumIndex].isPressed = 1;
|
||||
playSound(&drums[drumIndex]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* called from main event loop */
|
||||
void
|
||||
handleMouseButtonUp(SDL_Event * event)
|
||||
{
|
||||
int i;
|
||||
int mouseIndex = 0;
|
||||
/* check if this should cause any of the buttons to become unpressed */
|
||||
for (i = 0; i < NUM_DRUMS; i++) {
|
||||
if (buttons[i].touchIndex == mouseIndex) {
|
||||
buttons[i].isPressed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draws buttons to screen */
|
||||
void
|
||||
render(SDL_Renderer *renderer)
|
||||
{
|
||||
int i;
|
||||
SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);
|
||||
SDL_RenderClear(renderer); /* draw background (gray) */
|
||||
/* draw the drum buttons */
|
||||
for (i = 0; i < NUM_DRUMS; i++) {
|
||||
SDL_Color color =
|
||||
buttons[i].isPressed ? buttons[i].downColor : buttons[i].upColor;
|
||||
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
|
||||
SDL_RenderFillRect(renderer, &buttons[i].rect);
|
||||
}
|
||||
/* update the screen */
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
/*
|
||||
finds a sound channel in the mixer for a sound
|
||||
and sets it up to start playing
|
||||
*/
|
||||
int
|
||||
playSound(struct sound *s)
|
||||
{
|
||||
/*
|
||||
find an empty channel to play on.
|
||||
if no channel is available, use oldest channel
|
||||
*/
|
||||
int i;
|
||||
int selected_channel = -1;
|
||||
int oldest_channel = 0;
|
||||
|
||||
if (mixer.numSoundsPlaying == 0) {
|
||||
/* we're playing a sound now, so start audio callback back up */
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
/* find a sound channel to play the sound on */
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (mixer.channels[i].position == NULL) {
|
||||
/* if no sound on this channel, select it */
|
||||
selected_channel = i;
|
||||
break;
|
||||
}
|
||||
/* if this channel's sound is older than the oldest so far, set it to oldest */
|
||||
if (mixer.channels[i].timestamp <
|
||||
mixer.channels[oldest_channel].timestamp)
|
||||
oldest_channel = i;
|
||||
}
|
||||
|
||||
/* no empty channels, take the oldest one */
|
||||
if (selected_channel == -1)
|
||||
selected_channel = oldest_channel;
|
||||
else
|
||||
mixer.numSoundsPlaying++;
|
||||
|
||||
/* point channel data to wav data */
|
||||
mixer.channels[selected_channel].position = s->buffer;
|
||||
mixer.channels[selected_channel].remaining = s->length;
|
||||
mixer.channels[selected_channel].timestamp = SDL_GetTicks();
|
||||
|
||||
return selected_channel;
|
||||
}
|
||||
|
||||
/*
|
||||
Called from SDL's audio system. Supplies sound input with data by mixing together all
|
||||
currently playing sound effects.
|
||||
*/
|
||||
void
|
||||
audioCallback(void *userdata, Uint8 * stream, int len)
|
||||
{
|
||||
int i;
|
||||
int copy_amt;
|
||||
SDL_memset(stream, mixer.outputSpec.silence, len); /* initialize buffer to silence */
|
||||
/* for each channel, mix in whatever is playing on that channel */
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (mixer.channels[i].position == NULL) {
|
||||
/* if no sound is playing on this channel */
|
||||
continue; /* nothing to do for this channel */
|
||||
}
|
||||
|
||||
/* copy len bytes to the buffer, unless we have fewer than len bytes remaining */
|
||||
copy_amt =
|
||||
mixer.channels[i].remaining <
|
||||
len ? mixer.channels[i].remaining : len;
|
||||
|
||||
/* mix this sound effect with the output */
|
||||
SDL_MixAudioFormat(stream, mixer.channels[i].position,
|
||||
mixer.outputSpec.format, copy_amt, SDL_MIX_MAXVOLUME);
|
||||
|
||||
/* update buffer position in sound effect and the number of bytes left */
|
||||
mixer.channels[i].position += copy_amt;
|
||||
mixer.channels[i].remaining -= copy_amt;
|
||||
|
||||
/* did we finish playing the sound effect ? */
|
||||
if (mixer.channels[i].remaining == 0) {
|
||||
mixer.channels[i].position = NULL; /* indicates no sound playing on channel anymore */
|
||||
mixer.numSoundsPlaying--;
|
||||
if (mixer.numSoundsPlaying == 0) {
|
||||
/* if no sounds left playing, pause audio callback */
|
||||
SDL_PauseAudio(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int done; /* has user tried to quit ? */
|
||||
SDL_Window *window; /* main window */
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Event event;
|
||||
int i;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
|
||||
fatalError("could not initialize SDL");
|
||||
}
|
||||
window = SDL_CreateWindow(NULL, 0, 0, 320, 480, SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
renderer = SDL_CreateRenderer(window, 0, 0);
|
||||
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
|
||||
/* initialize the mixer */
|
||||
SDL_memset(&mixer, 0, sizeof(mixer));
|
||||
/* setup output format */
|
||||
mixer.outputSpec.freq = 44100;
|
||||
mixer.outputSpec.format = AUDIO_S16LSB;
|
||||
mixer.outputSpec.channels = 2;
|
||||
mixer.outputSpec.samples = 256;
|
||||
mixer.outputSpec.callback = audioCallback;
|
||||
mixer.outputSpec.userdata = NULL;
|
||||
|
||||
/* open audio for output */
|
||||
if (SDL_OpenAudio(&mixer.outputSpec, NULL) != 0) {
|
||||
fatalError("Opening audio failed");
|
||||
}
|
||||
|
||||
/* load our drum noises */
|
||||
loadSound("ds_kick_big_amb.wav", &drums[3]);
|
||||
loadSound("ds_brush_snare.wav", &drums[2]);
|
||||
loadSound("ds_loose_skin_mute.wav", &drums[1]);
|
||||
loadSound("ds_china.wav", &drums[0]);
|
||||
|
||||
/* setup positions, colors, and state of buttons */
|
||||
initializeButtons(renderer);
|
||||
|
||||
/* enter main loop */
|
||||
done = 0;
|
||||
while (!done) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
handleMouseButtonDown(&event);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
handleMouseButtonUp(&event);
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
render(renderer); /* draw buttons */
|
||||
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
/* cleanup code, let's free up those sound buffers */
|
||||
for (i = 0; i < NUM_DRUMS; i++) {
|
||||
SDL_free(drums[i].buffer);
|
||||
}
|
||||
/* let SDL do its exit code */
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
92
Xcode-iOS/Demos/src/rectangles.c
Normal file
92
Xcode-iOS/Demos/src/rectangles.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* rectangles.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include <time.h>
|
||||
#include "common.h"
|
||||
|
||||
void
|
||||
render(SDL_Renderer *renderer)
|
||||
{
|
||||
Uint8 r, g, b;
|
||||
int renderW;
|
||||
int renderH;
|
||||
|
||||
SDL_RenderGetLogicalSize(renderer, &renderW, &renderH);
|
||||
|
||||
/* Come up with a random rectangle */
|
||||
SDL_Rect rect;
|
||||
rect.w = randomInt(64, 128);
|
||||
rect.h = randomInt(64, 128);
|
||||
rect.x = randomInt(0, renderW);
|
||||
rect.y = randomInt(0, renderH);
|
||||
|
||||
/* Come up with a random color */
|
||||
r = randomInt(50, 255);
|
||||
g = randomInt(50, 255);
|
||||
b = randomInt(50, 255);
|
||||
|
||||
/* Fill the rectangle in the color */
|
||||
SDL_SetRenderDrawColor(renderer, r, g, b, 255);
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
|
||||
/* update screen */
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
int done;
|
||||
SDL_Event event;
|
||||
int windowW;
|
||||
int windowH;
|
||||
|
||||
/* initialize SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
fatalError("Could not initialize SDL");
|
||||
}
|
||||
|
||||
/* seed random number generator */
|
||||
srand(time(NULL));
|
||||
|
||||
/* create window and renderer */
|
||||
window = SDL_CreateWindow(NULL, 0, 0, 320, 480, SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
if (window == 0) {
|
||||
fatalError("Could not initialize Window");
|
||||
}
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
if (!renderer) {
|
||||
fatalError("Could not create renderer");
|
||||
}
|
||||
|
||||
SDL_GetWindowSize(window, &windowW, &windowH);
|
||||
SDL_RenderSetLogicalSize(renderer, windowW, windowH);
|
||||
|
||||
/* Fill screen with black */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
/* Enter render loop, waiting for user to quit */
|
||||
done = 0;
|
||||
while (!done) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
render(renderer);
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
/* shutdown SDL */
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
129
Xcode-iOS/Demos/src/touch.c
Normal file
129
Xcode-iOS/Demos/src/touch.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* touch.c
|
||||
* written by Holmes Futrell
|
||||
* use however you want
|
||||
*/
|
||||
|
||||
#include "SDL.h"
|
||||
#include <math.h>
|
||||
#include "common.h"
|
||||
|
||||
#define BRUSH_SIZE 32 /* width and height of the brush */
|
||||
#define PIXELS_PER_ITERATION 5 /* number of pixels between brush blots when forming a line */
|
||||
|
||||
static SDL_Texture *brush = 0; /* texture for the brush */
|
||||
|
||||
/*
|
||||
draws a line from (startx, starty) to (startx + dx, starty + dy)
|
||||
this is accomplished by drawing several blots spaced PIXELS_PER_ITERATION apart
|
||||
*/
|
||||
void
|
||||
drawLine(SDL_Renderer *renderer, float startx, float starty, float dx, float dy)
|
||||
{
|
||||
|
||||
float distance = sqrt(dx * dx + dy * dy); /* length of line segment (pythagoras) */
|
||||
int iterations = distance / PIXELS_PER_ITERATION + 1; /* number of brush sprites to draw for the line */
|
||||
float dx_prime = dx / iterations; /* x-shift per iteration */
|
||||
float dy_prime = dy / iterations; /* y-shift per iteration */
|
||||
SDL_Rect dstRect; /* rect to draw brush sprite into */
|
||||
float x;
|
||||
float y;
|
||||
int i;
|
||||
|
||||
dstRect.w = BRUSH_SIZE;
|
||||
dstRect.h = BRUSH_SIZE;
|
||||
|
||||
/* setup x and y for the location of the first sprite */
|
||||
x = startx - BRUSH_SIZE / 2.0f;
|
||||
y = starty - BRUSH_SIZE / 2.0f;
|
||||
|
||||
/* draw a series of blots to form the line */
|
||||
for (i = 0; i < iterations; i++) {
|
||||
dstRect.x = x;
|
||||
dstRect.y = y;
|
||||
/* shift x and y for next sprite location */
|
||||
x += dx_prime;
|
||||
y += dy_prime;
|
||||
/* draw brush blot */
|
||||
SDL_RenderCopy(renderer, brush, NULL, &dstRect);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
loads the brush texture
|
||||
*/
|
||||
void
|
||||
initializeTexture(SDL_Renderer *renderer)
|
||||
{
|
||||
SDL_Surface *bmp_surface;
|
||||
bmp_surface = SDL_LoadBMP("stroke.bmp");
|
||||
if (bmp_surface == NULL) {
|
||||
fatalError("could not load stroke.bmp");
|
||||
}
|
||||
brush =
|
||||
SDL_CreateTextureFromSurface(renderer, bmp_surface);
|
||||
SDL_FreeSurface(bmp_surface);
|
||||
if (brush == 0) {
|
||||
fatalError("could not create brush texture");
|
||||
}
|
||||
/* additive blending -- laying strokes on top of eachother makes them brighter */
|
||||
SDL_SetTextureBlendMode(brush, SDL_BLENDMODE_ADD);
|
||||
/* set brush color (red) */
|
||||
SDL_SetTextureColorMod(brush, 255, 100, 100);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
int x, y, dx, dy; /* mouse location */
|
||||
Uint8 state; /* mouse (touch) state */
|
||||
SDL_Event event;
|
||||
SDL_Window *window; /* main window */
|
||||
SDL_Renderer *renderer;
|
||||
int done; /* does user want to quit? */
|
||||
int w, h;
|
||||
|
||||
/* initialize SDL */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
fatalError("Could not initialize SDL");
|
||||
}
|
||||
|
||||
/* create main window and renderer */
|
||||
window = SDL_CreateWindow(NULL, 0, 0, 320, 480, SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
renderer = SDL_CreateRenderer(window, 0, 0);
|
||||
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
SDL_RenderSetLogicalSize(renderer, w, h);
|
||||
|
||||
/* load brush texture */
|
||||
initializeTexture(renderer);
|
||||
|
||||
/* fill canvass initially with all black */
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
done = 0;
|
||||
while (!done && SDL_WaitEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
done = 1;
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
state = SDL_GetMouseState(&x, &y); /* get its location */
|
||||
SDL_GetRelativeMouseState(&dx, &dy); /* find how much the mouse moved */
|
||||
if (state & SDL_BUTTON_LMASK) { /* is the mouse (touch) down? */
|
||||
drawLine(renderer, x - dx, y - dy, dx, dy); /* draw line segment */
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
SDL_DestroyTexture(brush);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue