Cocos2dx 3d open source project fantasyWarrior3D starts from and ends [AttackManager & amp; GameMaster] And cocos2dx open source games

Source: Internet
Author: User

Cocos2dx 3d open source project fantasyWarrior3D starts from and ends [AttackManager & GameMaster] And cocos2dx open source games
[AttackCommand] 1. Declare the basic collision body as the attack unit released by the role

BasicCollider = class ("BasicCollider", function ()
    local node = cc.Node: create ()
    node: setCascadeColorEnabled (true)
    return node
end)

function BasicCollider: ctor ()
    self.minRange = 0 --the min radius of the fan
    self.maxRange = 150 --the max radius of the fan
    self.angle = 120 --arc of attack, in radians
    self.knock = 150 --default knock, knocks 150 units
    self.mask = 1 --1 is Heroes, 2 is enemy, 3 ??
    self.damage = 100
    self.facing = 0 --this is radians
    self.duration = 0
    self.curDuration = 0
    self.speed = 0 --traveling speed}
    self.criticalChance = 0
end


The specific parameters of each role are configured in GlobalVariables.lua
angle Attack angle, very useful, related to skills and the scope of attack
MaxRange attack scope

These two parameters can determine a "skill application area", which can be easily realized such as "fan-shaped" attack area
In this way, the attack skills do not necessarily need to be triggered by BasicCollider colliding with the target, as long as the enemy is in the attack area, it can be considered hit.

speed The speed at which the attacking body moves. For the attack of a warrior or the "ice wall" of a mage, the speed is 0
duration
DOTTimer continuous damage cd

You can also add an attribute maxTarget to determine whether a skill can be absorbed by a single body or can penetrate a target.
Act on multiple targets. For example, in Dota, Daniel "Shockwave" Lich "Serial Frost", etc.

2. AttackManager All released attack units are placed in AttackManager
solveAttacks attack unit frame loop
There are 3 main things done:

[1] Determine whether "hit"
The onCollide attack takes effect: the condition is that the distance and angle are satisfied

_myPos will keep updating with the game
function Actor: baseUpdate (dt)
    self._myPos = getPosTable (self)
    ...
end

Calculate the angle required for the attack unit to turn to the target
local angle = radNormalize (cc.pToAngleSelf (cc.pSub (mpos, apos)))


Calculate the direction of the attacking unit
local afacing = radNormalize (attack.facing)

Determine if you are in the attack zone

if (afacing + attack.angle / 2)> angle and angle> (afacing- attack.angle / 2) then
    attack: onCollide (monster)
end

[2] Judge timeout according to duration
onTimeOut remove attack unit

[3] Update location according to speed
onUpdate

3. Inherit the basic attack units to achieve various character skills. Then take a look at how the mage's "ice wall" does
Mage: specialAttack ()
among them
local pos1 = getPosTable (self)
local pos2 = getPosTable (self)
local pos3 = getPosTable (self)
pos1.x = pos1.x + 130
pos2.x = pos2.x + 330
pos3.x = pos3.x + 530
pos1 = cc.pRotateByAngle (pos1, self._myPos, self._curFacing)
pos2 = cc.pRotateByAngle (pos2, self._myPos, self._curFacing)
pos3 = cc.pRotateByAngle (pos3, self._myPos, self._curFacing)

pRotateByAngle returns the point to pos1 with self._myPos as the rotation axis, and rotates self._curFacing in a counterclockwise direction,
In this way, three points are finally obtained. They are 130 330 530 from the mage on the line between the mage and the target. Created 3 MageIceSpikes at these 3 points

MageIceSpikes.create

Randomly consist of 10 ice spikes, and add particle effects

Attributes:
    _specialAttack = {
        minRange = 0,
        maxRange = 140,
        angle = DEGREES_TO_RADIANS (360),
        knock = 75,
        damage = 250,
        mask = EnumRaceType.HERO,
        duration = 4.5,
        speed = 0,
        criticalChance = 0.05,
        DOTTimer = 0.75, --it will be able to hurt every 0.5 seconds
        curDOTTime = 0.75,
        DOTApplied = false
    },




[GameMaster]
GameMaster: init () can be seen from
Create characters in a unified manner and release them in batches

self: AddHeros ()
self: addMonsters ()
logicUpdate frame loop
Mainly responsible for controlling the progress of the hero and the refresh of the mobs

local battleSiteX = {-2800, -1800, -800}
Set the trigger location and refresh location

stage is 1 ~ 7
Randomly spawn or run to the right

stage == 7 clear the mobs
stage == 8 give warning

After the warning, the boss is displayed showBoss ()
It is not very configurable, so the code will not be analyzed here.

[ParticleManager] The plist contains two parts: particle system properties and particle texture

1. Load and create Quad particle objects with particle attributes. At startup, call AddPlistData to load the plist file of particles, and the cache is in map format.
From the interface implementation point of view, if the particles are created directly from the cached map, it saves the time of reading the file and plays an optimization role.
ParticleSystemQuad * ParticleSystemQuad :: create (ValueMap & dictionary)
{
    ParticleSystemQuad * ret = new (std :: nothrow) ParticleSystemQuad ();
    if (ret && ret-> initWithDictionary (dictionary))
    {
        ret-> autorelease ();
        return ret;
    }
    CC_SAFE_DELETE (ret);
    return ret;
}


2. Particle texture provided by FX.plist and FX.png
Texture the generated quad
magic: setTextureWithRect (magicf: getTexture (), magicf: getRect ())


3. Error about the console During debugging, the console has been reporting bugs, so I went to see the source code now and then, by the way, see how the overload of the lua function ParticleSystemQuad: create is implemented
error:
     cc.ParticleSystemQuad: create argument # 2 is 'table'; 'string' expected.

int lua_cocos2dx_ParticleSystemQuad_create (lua_State * tolua_S)
{
    int argc = 0;
    bool ok = true;
#if COCOS2D_DEBUG> = 1
    tolua_Error tolua_err;
#endif


#if COCOS2D_DEBUG> = 1
    if (! tolua_isusertable (tolua_S, 1, "cc.ParticleSystemQuad", 0, & tolua_err)) goto tolua_lerror;
#endif


    argc = lua_gettop (tolua_S) -1;


    do
    {
        if (argc == 1)
        {
            std :: string arg0;
            ok & = luaval_to_std_string (tolua_S, 2, & arg0, "cc.ParticleSystemQuad: create");
            if (! ok) {break;}
            cocos2d :: ParticleSystemQuad * ret = cocos2d :: ParticleSystemQuad :: create (arg0);
            object_to_luaval <cocos2d :: ParticleSystemQuad> (tolua_S, "cc.ParticleSystemQuad", (cocos2d :: ParticleSystemQuad *) ret);
            return 1;
        }
    } while (0);
    ok = true;
    do
    {
        if (argc == 0)
        {
            cocos2d :: ParticleSystemQuad * ret = cocos2d :: ParticleSystemQuad :: create ();
            object_to_luaval <cocos2d :: ParticleSystemQuad> (tolua_S, "cc.ParticleSystemQuad", (cocos2d :: ParticleSystemQuad *) ret);
            return 1;
        }
    } while (0);
    ok = true;
    do
    {
        if (argc == 1)
        {
            cocos2d :: ValueMap arg0;
            ok & = luaval_to_ccvaluemap (tolua_S, 2, & arg0, "cc.ParticleSystemQuad: create");
            if (! ok) {break;}
            cocos2d :: ParticleSystemQuad * ret = cocos2d :: ParticleSystemQuad :: create (arg0);
            object_to_luaval <cocos2d :: ParticleSystemQuad> (tolua_S, "cc.ParticleSystemQuad", (cocos2d :: ParticleSystemQuad *) ret);
            return 1;
        }
    } while (0);
    ok = true;


After reading the source code overloading, the idea is relatively clear: first determine the number of parameters, and then try to take the parameters in the L stack through the function luaval_to_std_string, respectively, until a certain type is correctly obtained
ok & = luaval_to_std_string (tolua_S, 2, & arg0, "cc.ParticleSystemQuad: create");

The error log is reported by the function luaval_to_native_err during the trial process

    if (! tolua_iscppstring (L, lo, 0, & tolua_err))
    {
#if COCOS2D_DEBUG> = 1
        luaval_to_native_err (L, "# ferror:", & tolua_err, funcName);
#endif
        ok = false;
    }

Think about it a little bit. In fact, this code can be optimized. You can try all the branches you want to try first, and report errors if they are not correct.

[manager]
Maintain all the role objects, mainly responsible for handling collision events

collisionDetect frame loop
collision (sprite)-> solveCollision
Make sure the distance between the two characters is less than the "waistline" _radius of the two, and calculate the distance of the bounce based on the "weight" _mass of the two

isOutOfBound (sprite) ensures that the character will not come out of the screen
G =
{
    winSize = cc.Director: getInstance (): getWinSize (),
    bloodPercentDropSpeed = 2,
    activearea = {left = -2800, right = 1000, bottom = 100, top = 700},
}

getFocusPointOfHeros Get the hero's "average position" as the camera focus


reference:


"particle"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.