Updated iOS tests and demos for latest SDL linking requirements

This commit is contained in:
Sam Lantinga 2020-11-06 13:03:07 -08:00
parent e87fbb1aa7
commit 1bd4b7fdf1
38 changed files with 8145 additions and 1 deletions

View 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;
}

View 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;
}

View 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);

View 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
View 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;
}

View 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
View 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;
}

View 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
View 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;
}