Lightning Lag- Cocos2d

时间:2012-04-30 01:54:56

标签: iphone cocos2d-iphone

我有几个物体从屏幕顶部“掉落”,当它们被敲击时,闪电击中它们。我的问题是,当其中一个物体被敲击并且闪电击中时,我的FPS下降并且游戏滞后。

有人可以帮助我减少这种滞后或引导我朝着正确的方向前进吗?我不知道如何解决它。我的比赛结束了,这是阻止我回来的唯一事情......

这是闪电代码。

Lightning.h

//
//  Lightning.h
//  Trundle
//
//  Created by Robert Blackwood on 12/1/09.
//  Copyright 2009 Mobile Bros. All rights reserved.
//

#import "cocos2d.h"

/*! This will draw lighting and return the midpoint */
CGPoint drawLightning(CGPoint pt1, CGPoint pt2, int displace, int minDisplace, unsigned long randSeed, float width);
void drawSmoothLine(CGPoint *pos1, CGPoint *pos2, float width);
void drawSmoothPointAt(CGPoint *pos, float width);
void fillSmoothRectangle(CGRect *r, float width);

@interface Lightning : CCNode <CCRGBAProtocol>
{
    CGPoint _strikePoint;
    CGPoint _strikePoint2;
    CGPoint _strikePoint3;

    ccColor3B   _color;
    GLubyte     _opacity;
    BOOL        _split;
    BOOL        _glow;

    int _displacement;
    int _minDisplacement;
    float _lighteningWidth;

    unsigned long _seed;
}

@property (readwrite, assign) CGPoint strikePoint;
@property (readwrite, assign) CGPoint strikePoint2;
@property (readwrite, assign) CGPoint strikePoint3;
@property (readwrite, assign) ccColor3B color;
@property (readwrite, assign) GLubyte opacity;
@property (readwrite, assign) BOOL split;
@property (readwrite, assign) BOOL glow;
@property (readwrite, assign) int displacement;
@property (readwrite, assign) int minDisplacement;
@property (readwrite, assign) float lighteningWidth;
@property (readwrite, assign) unsigned long seed;

+(id) lightningWithStrikePoint:(CGPoint)strikePoint strikePoint2:(CGPoint)strikePoint2;

-(id) initWithStrikePoint:(CGPoint)strikePoint strikePoint2:(CGPoint)strikePoint2;

-(void) strikeRandom;
-(void) fade;

@end

Lightning.m

//
//  Lightning.m
//  Trundle
//
//  Created by Robert Blackwood on 12/1/09.
//  Copyright 2009 Mobile Bros. All rights reserved.
//

#import "Lightning.h"

@implementation Lightning

@synthesize strikePoint = _strikePoint;
@synthesize strikePoint2 = _strikePoint2;
@synthesize strikePoint3 = _strikePoint3;
@synthesize color = _color;
@synthesize opacity = _opacity;
@synthesize displacement = _displacement;
@synthesize minDisplacement = _minDisplacement;
@synthesize lighteningWidth = _lighteningWidth;
@synthesize seed = _seed;
@synthesize split = _split;
@synthesize glow = _glow;

+(id) lightningWithStrikePoint:(CGPoint)strikePoint strikePoint2:(CGPoint)strikePoint2
{
    return [[[self alloc] initWithStrikePoint:strikePoint strikePoint2:strikePoint2] autorelease];
}

-(id) initWithStrikePoint:(CGPoint)strikePoint strikePoint2:(CGPoint)strikePoint2
{
    if ((self = [super init]))
    {
        _strikePoint = strikePoint;
        _strikePoint2 = ccp(0, 0);
        _strikePoint3 = strikePoint2;

        _color = ccc3(255, 190, 255);

        //random style
        _displacement = 100 + CCRANDOM_0_1() * 200;
        _minDisplacement = 4 + CCRANDOM_0_1() * 10;
        _lighteningWidth = 2.0f;
        _split = YES;
        _glow = YES;

        [self strikeRandom];
    }

    return self;
}

-(void) draw
{
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glColor4ub(_color.r, _color.g, _color.b, _opacity);

    drawLightning(_strikePoint3, _strikePoint, _displacement, _minDisplacement, _seed, _lighteningWidth);

    if (_glow)
    {
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        glColor4ub(50, 0, 255, _opacity);
        drawLightning(_strikePoint3, _strikePoint, _displacement, _minDisplacement, _seed, 7);
    }

    if (_opacity != 255)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    if (_opacity != 255)
        glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);

    glColor4f(1.0, 1.0, 1.0, 1.0);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D);
}

-(void) strikeRandom
{
    _glow = YES;
    _seed = rand();
    [self fade];
}

- (void) removeLightning {
    self.visible = NO;
}

- (void) fade
{
    self.visible = YES;
    self.opacity = 255;

    [self runAction:[CCSequence actions: 
                    // [DelayTime actionWithDuration:1.0],
                     [CCShow action],
                     [CCFadeOut actionWithDuration:0.5],
                     [CCCallFunc actionWithTarget:self selector:@selector(removeLightning)],
                     nil]];
}

-(void)dealloc
{
    [super dealloc];
}

@end

int getNextRandom(unsigned long *seed)
{
    //taken off a linux site (linux.die.net)
    (*seed) = (*seed) * 1103515245 + 12345;
    return ((unsigned)((*seed)/65536)%32768);
}

CGPoint drawLightning(CGPoint pt1, CGPoint pt2, int displace, int minDisplace, unsigned long randSeed, float width)
{   
    CGPoint mid = ccpMult(ccpAdd(pt1,pt2), 0.5f);

    if (displace < minDisplace)
    {
        //ccDrawLine(pt1, pt2);
        drawSmoothLine(&pt1, &pt2, width);
        drawSmoothPointAt(&mid, width);
    }
    else
    {
        int r = getNextRandom(&randSeed);
        mid.x += (((r % 101)/100.0)-.5)*displace;
        r = getNextRandom(&randSeed);
        mid.y += (((r % 101)/100.0)-.5)*displace;

        drawLightning(pt1,mid,displace/2,minDisplace,randSeed,width);
        drawLightning(pt2,mid,displace/2,minDisplace,randSeed,width);
    }

    return mid;
} 

void drawSmoothLine(CGPoint *pos1, CGPoint *pos2, float width)
{
    GLfloat lineVertices[12], currentColor[4]; 
    GLint   red, green, blue, alpha;
    CGPoint dir, tan;

    dir.x = pos2->x - pos1->x;
    dir.y = pos2->y - pos1->y;
    float len = sqrtf(dir.x * dir.x + dir.y * dir.y);
    if(len < 0.00001)
        return;
    dir.x = dir.x / len;
    dir.y = dir.y / len;
    tan.x = -width * dir.y;
    tan.y = width * dir.x;

    lineVertices[0] = pos1->x + tan.x;
    lineVertices[1] = pos1->y + tan.y;
    lineVertices[2] = pos2->x + tan.x;
    lineVertices[3] = pos2->y + tan.y;
    lineVertices[4] = pos1->x;
    lineVertices[5] = pos1->y;
    lineVertices[6] = pos2->x;
    lineVertices[7] = pos2->y;
    lineVertices[8] = pos1->x - tan.x;
    lineVertices[9] = pos1->y - tan.y;
    lineVertices[10] = pos2->x - tan.x;
    lineVertices[11] = pos2->y - tan.y;

    glGetFloatv(GL_CURRENT_COLOR, currentColor);
    red = 255.0 * currentColor[0];
    green = 255.0 * currentColor[1];
    blue = 255.0 * currentColor[2];
    alpha = 255.0 * currentColor[3];

    const GLubyte lineColors[] = {
        red, green, blue, 0,
        red, green, blue, 0,
        red, green, blue, alpha,
        red, green, blue, alpha,
        red, green, blue, 0,
        red, green, blue, 0,
    };

    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glVertexPointer(2, GL_FLOAT, 0, lineVertices);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, lineColors);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);

    glDisableClientState(GL_COLOR_ARRAY);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D);
}

void drawSmoothPointAt(CGPoint *position, float width)
{
    GLfloat pntVertices[2*6], currentColor[4]; 
    GLint   red, green, blue, alpha;

    pntVertices[0] = position->x;
    pntVertices[1] = position->y;
    pntVertices[2] = position->x - width;
    pntVertices[3] = position->y - width;
    pntVertices[4] = position->x - width;
    pntVertices[5] = position->y + width;
    pntVertices[6] = position->x + width;
    pntVertices[7] = position->y + width;
    pntVertices[8] = position->x + width;
    pntVertices[9] = position->y - width;
    pntVertices[10] = position->x - width;
    pntVertices[11] = position->y - width;

    glGetFloatv(GL_CURRENT_COLOR, currentColor);
    red = 255.0 * currentColor[0];
    green = 255.0 * currentColor[1];
    blue = 255.0 * currentColor[2];
    alpha = 255.0 * currentColor[3];

    const GLubyte pntColors[] = {
        red, green, blue, alpha,
        red, green, blue, 0,
        red, green, blue, 0,
        red, green, blue, 0,
        red, green, blue, 0,
        red, green, blue, 0,
    };

    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glVertexPointer(2, GL_FLOAT, 0, pntVertices);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, pntColors);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

    glDisableClientState(GL_COLOR_ARRAY);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D);
}

2 个答案:

答案 0 :(得分:1)

你正在做太多计算以获得你想要的效果

我不想让你重写你的代码..但是通过点

来看待贝塞尔曲线

here就是我的意思(将张力设置为0.5或smth ..以获得闪电般的效果)

这样做......或者只是制作一堆或随机生成的图像(闪电),然后将它们放在图像的顶部以获得闪电效果。你所做的对于小型设备而言太贵了

答案 1 :(得分:1)

如果您将闪电作为PNG图像导入批处理节点纹理,您的FPS将大大提高。假设您同时从不同方向发射多个闪电图像,这只会导致一次调用OpenGL,并且该调用将没有绘图逻辑,因为图像已经在应用程序外部创建。