Skip to content

Instantly share code, notes, and snippets.

@lukaswelte
Created April 9, 2013 19:04
Show Gist options
  • Save lukaswelte/5348440 to your computer and use it in GitHub Desktop.
Save lukaswelte/5348440 to your computer and use it in GitHub Desktop.
TinyWings ground infinite modification
#import <Foundation/Foundation.h>
#import "Box2D.h"
#define kMaxHillKeyPoints 10
#define kMaxHillVertices 1000
#define kMaxBorderVertices 5000
#define kHillSegmentWidth 10
@interface Ground : CCNode {
ccVertex2F hillKeyPoints[kMaxHillKeyPoints];
int nHillKeyPoints;
int fromKeyPointI;
int toKeyPointI;
ccVertex2F hillVertices[kMaxHillVertices];
ccVertex2F hillTexCoords[kMaxHillVertices];
int nHillVertices;
ccVertex2F borderVertices[kMaxBorderVertices];
int nBorderVertices;
float _offsetX;
float _offsetY;
float _length;
b2World *world;
b2Body *body;
int screenW;
int screenH;
int textureSize;
}
@property (nonatomic, strong) CCSprite *stripes;
@property (nonatomic, assign) float groundStartY;
@property (nonatomic, assign) float groundEndY;
@property (nonatomic, assign) float xPosition;
+ (id) groundWithWorld:(b2World*)w andLength:(int)lenght andOffsetX:(float)xOffset Y:(float)yOffset;
- (id) initWithWorld:(b2World*)w andLength:(int)lenght andOffsetX:(float)xOffset Y:(float)yOffset;
- (void) reset;
@end
#import "Ground.h"
@interface Ground()
- (CCSprite*) generateGroundSprite;
- (CCTexture2D*) generateGroundTexture;
- (void) renderGround;
- (void) generateHillKeyPoints;
- (void) generateBorderVertices;
@end
@implementation Ground
+ (id) groundWithWorld:(b2World*)w andLength:(int)lenght andOffsetX:(float)xOffset Y:(float)yOffset {
return [[self alloc] initWithWorld:w andLength:lenght andOffsetX:xOffset Y:yOffset];
}
- (id) initWithWorld:(b2World*)w andLength:(int)lenght andOffsetX:(float)xOffset Y:(float)yOffset {
if ((self = [super init])) {
world = w;
CGSize size = [[CCDirector sharedDirector] winSize];
screenW = size.width;
screenH = size.height;
textureSize = 512;
_offsetX = _xPosition = xOffset;
_offsetY = _groundEndY = yOffset;
_length = lenght;
self.stripes = [self generateGroundSprite];
[self generateHillKeyPoints];
[self generateBorderVertices];
[self createHillVertices];
}
return self;
}
- (void) dealloc {
self.stripes = nil;
}
- (CCSprite*) generateGroundSprite {
CCTexture2D *texture = [self generateGroundTexture];
CCSprite *sprite = [CCSprite spriteWithTexture:texture];
ccTexParams tp = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_CLAMP_TO_EDGE};
[sprite.texture setTexParameters:&tp];
return sprite;
}
- (CCTexture2D*) generateGroundTexture {
CCRenderTexture *rt = [CCRenderTexture renderTextureWithWidth:1024 height:256];
[rt begin];
[self renderGround];
[rt end];
return rt.sprite.texture;
}
- (void) renderGround {
CCSprite *s = [CCSprite spriteWithFile:@"groundTexture.png"];
s.anchorPoint = ccp(0,0);
s.position = ccp(0, 0);
[s visit];
[s visit]; // more contrast
}
- (void) generateHillKeyPoints {
nHillKeyPoints = 0;
float x, y, dx, dy, ny;
// starting point
x = 0;
y = _offsetY;
hillKeyPoints[nHillKeyPoints++] = (ccVertex2F){x, y};
// middle points
int minDX = round(_length/11), rangeDX = round(_length/22);
int minDY = 25, rangeDY = 35;
float sign = -1; // +1 - going up, -1 - going down
float maxHeight = 60;
float minHeight = 10;
while (nHillKeyPoints < kMaxHillKeyPoints-2) {
dx = arc4random()%rangeDX+minDX;
x += dx;
dy = arc4random()%rangeDY+minDY;
ny = y + dy*sign;
if(ny > maxHeight) ny = maxHeight;
if(ny < minHeight) ny = minHeight;
y = ny;
sign *= -1;
hillKeyPoints[nHillKeyPoints++] = (ccVertex2F){x, y};
}
x = _length;
dy = arc4random()%rangeDY+minDY;
ny = y + dy*sign;
if(ny > maxHeight) ny = maxHeight;
if(ny < minHeight) ny = minHeight;
y = ny;
_groundEndY = y;
hillKeyPoints[nHillKeyPoints++] = (ccVertex2F){x, y};
}
- (void) generateBorderVertices {
nBorderVertices = 0;
ccVertex2F p0, p1, pt0, pt1;
p0 = hillKeyPoints[0];
for (int i=1; i<nHillKeyPoints; i++) {
p1 = hillKeyPoints[i];
int hSegments = floorf((p1.x-p0.x)/kHillSegmentWidth-1);
float dx = (p1.x - p0.x) / hSegments;
float da = M_PI / hSegments;
float ymid = (p0.y + p1.y) / 2;
float ampl = (p0.y - p1.y) / 2;
pt0 = p0;
borderVertices[nBorderVertices++] = pt0;
for (int j=1; j<hSegments+1; j++) {
pt1.x = p0.x + j*dx;
pt1.y = ymid + ampl * cosf(da*j);
borderVertices[nBorderVertices++] = pt1;
pt0 = pt1;
}
p0 = p1;
}
}
- (void) createHillVertices {
nHillVertices = 0;
ccVertex2F p0, p1;
p0 = borderVertices[0];
for (int i=1; i<nBorderVertices; i++) {;
p1 = borderVertices[i];
// triangle strip between p0 and p1
hillVertices[nHillVertices] = (ccVertex2F){p0.x, p0.y-(float)textureSize};
hillTexCoords[nHillVertices++] = (ccVertex2F){p0.x/(float)textureSize, 1.0f};
hillVertices[nHillVertices] = (ccVertex2F){p1.x, p1.y-(float)textureSize};
hillTexCoords[nHillVertices++] = (ccVertex2F){p1.x/(float)textureSize, 1.0f};
hillVertices[nHillVertices] = (ccVertex2F){p0.x, p0.y};
hillTexCoords[nHillVertices++] = (ccVertex2F){p0.x/(float)textureSize, 0};
hillVertices[nHillVertices] = (ccVertex2F){p1.x, p1.y};
hillTexCoords[nHillVertices++] = (ccVertex2F){p1.x/(float)textureSize , 0};
p0 = p1;
}
}
- (void) reset {
_offsetX = _xPosition;
_offsetY = _groundStartY;
[self generateHillKeyPoints];
[self generateBorderVertices];
[self createHillVertices];
}
- (void) draw {
self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTexture];
CC_NODE_DRAW_SETUP();
ccGLBindTexture2D( _stripes.texture.name );
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
[self.shaderProgram use];
[self.shaderProgram setUniformForModelViewProjectionMatrix];
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, sizeof(CGPoint), hillVertices);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, sizeof(CGPoint), hillTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)nHillVertices);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment