存档

2012年3月 的存档

Getting and setting the RGB / RGBA value of a pixel in a CCSprite (cocos2d-x)

2012年3月12日 没有评论

Why do I need this?

Basically I need to turn a color image into gray-scale. Including a gray-scale version of the image could be a solution, but space is tight in my situation – I don’t want my APK to be too big. Besides, I would like to work on the pixels for some effects too. Again, this is to make the APK smaller.

I have found getPixel setPixel from CCTexture2D and Getting image’s pixel RGBA, but I would like something more simple.

Any help is appreciated.

Thank you!

Here is my solution for you :

1.First make a CCImage version of your image:

I) from File :

CCImage *img=  new CCImage();
img->initWithImageFile("colors.png");

II) From Sprite :

  • II.1) CCSprite -> RenderTexture2D

  • II.2) RenderTexture2D -> CCImage (CCImage *testImage = RenderText2D->newCCImage();)

2.Then You can do what you need :

    CCImage *img= ... // make CCImage from CCSprite
    int x=3;
    if(img->hasAlpha())
        x=4;

    unsigned char *data = new unsigned char[img->getDataLen()*x];   
    data = img->getData();
    // [0][0] => Left-Top Pixel !
    // But cocos2d Location Y-axis is Bottom(0) to Top(max)

    for(int i=0;i<img->getWidth();i++)
    {
        for(int j=0;j<img->getHeight();j++)
        {
            unsigned char *pixel = data + (i + j * img->getWidth()) * x;

           // You can see/change pixels' RGBA value(0-255) here !
            unsigned char r = *pixel;
            unsigned char g = *(pixel + 1);
            unsigned char b = *(pixel + 2) ;
            unsigned char a = *(pixel + 3);
        }
    }

3.Then, convert it to texture_2D

//CCImage -> Texture2d
    texture_2D= new CCTexture2D();
    texture_2D->initWithImage(img);

4.And Finally back to CCSprite

CCSprite *result=  CCSprite::createWithTexture(texture_2D);

This can be done a couple of ways. What I have done in the past is to just called setColor on the sprite to some color close to what you are looking for. That had worked for my purposes.

my_sprite.setColor( ccc3( 128, 128, 128 ) );

Another solution (more thorough and precise):
how to implement grayscale rendering in OpenGL?

分类: stackoverflow精选, unity3d 标签:

Unity3D C# calculate correct forward after rotation

2012年3月10日 没有评论

I’m starting my development using Unity.
I’m doing something like that:

    if(Input.GetKey(KeyCode.A))newValues[1]-=this.turnSpeed*(float)Time.deltaTime;
    if(Input.GetKey(KeyCode.D))newValues[1]+=this.turnSpeed*(float)Time.deltaTime;
    transform.Rotate(0, newValues[1], 0);


    if(Input.GetKey(KeyCode.W))newValues[0]+=this.speed*transform.forward.z*(float)Time.deltaTime;
    if(Input.GetKey(KeyCode.S))newValues[0]-=this.speed*transform.forward.z*(float)Time.deltaTime;


    transform.position = new Vector3(transform.position.x, transform.position.y, (float)newValues[0]);

So i rotate and i can move, but it moves just in the Z line, i know i’m calling the Z specific movement.
But with Javascript i can do something

     transform.forward+=this.speed*transform.forward*(float)Time.deltaTime;

So i don’t need to do the new vector process and copy to a separate variable and it works like a charm, using the rotation and using as orientation to himself when it’s rotated.

you may misunderstand the usage of transform.forward.
transform.forward is just a vector to tell you what direction your gameObject face, it depends on transform.rotation.

If you want to move your GameObject, always use transform.position:

 transform.position += this.speed * transform.forward * (float)Time.deltaTime;
分类: stackoverflow精选, unity3d 标签:

研发游戏的那点事儿

2012年3月9日 没有评论

  如果一个程序员真的投入进去那个世界,是难以自拔出来。一个游戏世界的缔造者,那种成就和期待是任何东西都不可比拟的。以前喜欢玩金山的游戏,我有部分朋友以前是金山的,金山的技术那是行业内顶尖的。所以玩金山的游戏,我愿意花钱,我也不是金山的拖。现在一个个的大游戏公司:完美,网易,盛大,蜗牛,百游等这些都是国内顶尖的虚拟世界制造商。制作游戏和应用不同,这也有本质的区别,做游戏为了什么,为了赚钱,那做出来的游戏必定不好玩。而目前我并非专业从事游戏行业,但是我是怀揣着儿时的梦想实现这个游戏梦想,缔造出我心中的那款游戏,2010年开始进入游戏行业并开始对游戏研发,运营有所了解。每一个环节我都细细品味,慢慢琢磨。做网络游戏还不同于做单机游戏那么简单平常,而网游中有区分为3D,2D,2.5D,最后是目前比较盛行的无端网页游戏,一款不错的网游至少需要1年,甚至几年的推敲琢磨,酝酿。所以做游戏和酿酒一样,并非越快就越好。而是从量变到质变的过程。目前国内前几家拥有自主研发游戏引擎的公司都拥有强大的研发团队,蜗牛的九阴真经,完美世界的笑傲江湖。九阴从2010就开始宣传,上百人技术团队已近非常努力的为这款游戏打基础。游戏的引擎真的是非常赞的,也许大家在这个技术不断提升的社会已经对新技术产生了疲劳感了。玩家对画面的要求,对游戏性的要求已经太高太高。现在的游戏研发技术,玩家已经不再感兴趣,感兴趣的是怎么样打破玩家的观念,和创新,游戏性。正因如此,这些最求品质的游戏公司一再跳票。现在只要拿一款3D游戏出来,无论任何人,任何玩家,都要拿它来和魔兽比较。其实从技术层面和技术角度上说,九阴和笑傲的游戏品质是接近魔兽甚至是超越魔兽的。我只说品质,品质概括了【实景画质,游戏风格,玩法创新,游戏背景】衡量一款游戏的品质有很多元素,根据不同玩家不同选择。不过我比较支持国产网游。特别是武侠题材。中国武术是世界瑰宝。慢慢弘扬吧,呵呵。

      今天没有说技术,没有代码,只有简单的感叹而已。想想玩了十几年游戏。如今站在研发者得角度,考虑一款游戏的研发,制作,运营,的那点点滴滴。简简单单分析下来一款游戏需要有一个很健全的团队和运营团队才算成功。为什么腾讯要和金山合作,金山有技术,腾讯有运营!两样搭配起来才能将一款佳作推到巅峰,相信剑3这款游戏也有不少人玩过。希望越来越多的这样的精品游戏诞生。

      

分类: 未分类 标签:

移动终端网页游戏移植研发框架【带动画效果控件隐藏的方法】

2012年3月8日 没有评论

大家都知道:

控件名.setVisibility(View.GONE);能够在安卓里面隐藏控件,并且不占空间!

Ok,但是带动画效果的控件隐藏效果是不一样的。有一定区别,犹豫在视图中,setVisibility属性只是在静态的线程里面才能生效。

那么动态效果的时候setVisibility属性就会失效了。所以在这里介绍一点编程小技巧

首先我们看一下图:

移动终端网页游戏移植研发框架【带动画效果控件隐藏的方法】

上图可以看到有3个控件按钮,并且它们都是带有动画效果的控件,现在都是GONE状态,只显示动画开启的按钮效果。

要实现真正的能隐藏带动画效果的控件,必须有个先后顺序,然后再来启动按钮显示!

iv_chatliaoqiehuan.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Animation aniout = AnimationUtils.loadAnimation(getContext(),
						R.anim.playerinfo_state_out);
				aniout.setAnimationListener(new AnimationListener() {
					
					@Override
					public void onAnimationStart(Animation animation) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onAnimationRepeat(Animation animation) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onAnimationEnd(Animation animation) {
						// TODO Auto-generated method stub
						iv_chatliaoqiehuan.setVisibility(View.GONE);
					}
				});
				iv_chatliaoqiehuan.startAnimation(aniout);
				Animation aniin = AnimationUtils.loadAnimation(getContext(),
						R.anim.playerinfo_state_in);
				aniin.setAnimationListener(new AnimationListener() {
					
					@Override
					public void onAnimationStart(Animation animation) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onAnimationRepeat(Animation animation) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onAnimationEnd(Animation animation) {
						// TODO Auto-generated method stub
						ll_chatinfolist.setVisibility(View.VISIBLE);
						iv_chatyingqiehuan.setVisibility(View.VISIBLE);
					}
				});
				ll_chatinfolist.startAnimation(aniin);
				iv_chatyingqiehuan.startAnimation(aniin);
				
			}
		});

先将动画实例化,然后将

setAnimationListener方法监听实现,当动画播放完毕之后将界面隐藏或者显示,这样,整个界面的流畅和逻辑就正确了,用户使用起来也非常方便!
onAnimationEnd里面书写隐藏或者关闭的代码,当动画播放完毕之后执行操作。

移动终端网页游戏移植研发框架【带动画效果控件隐藏的方法】

如图,动画展开,关闭都有动画,并且,在动画播放完毕后都实现了隐藏。

剑神客栈研发官方群:【45578308】 欢迎一起参与讨论策划。

分类: 未分类 标签:

移动终端网页游戏移植研发框架【道具系统】

2012年3月5日 没有评论

前两天发随笔,居然没通过,有点郁闷,其实我是想和大家交流讨论网游研发技术,呵呵。写下在自己研发网游这几年来的心得和感受,同时也希望得到大家的支持,上星期周六周末都在家里面研发道具系统,周末晚上总算完工,下面写下我的心得:

道具的功能点如下:

1,道具使用【如果是装备,则为装备状态】

2,道具贩卖

3,道具丢弃

在游戏中的道具列表中有一些基本的默认值需要和人物属性挂钩,比如,一个人物有且只能有一个backprope的表,一个人物的背包容量上限【30格】。这个表存放所有道具的基本信息,道具包含【道具,装备,防具,武器,技能书】。下面我们具体看一下游戏界面

 

移动终端网页游戏移植研发框架【道具系统】

之后详细看一下界面里面的功能,将里面的包裹实体化,里面就是一个GridView其实,然后在做道具控件,装上一个背景图。

移动终端网页游戏移植研发框架【道具系统】OK 之后我们将这个道具控件装载进GridView里面,就达到我们要的效果了!

也面制作完毕,看下跑起来的效果。

如果没有道具的情况下显示这样的效果:

移动终端网页游戏移植研发框架【道具系统】

去练级地图打几个怪来试试道具的其他功能,首先我们要测试的是道具的使用,如果是装备,弹出来的提示框字体就应该为装备。

移动终端网页游戏移植研发框架【道具系统】

现在有4个道具,一个是武器,技能书,两瓶药。OK,分别看看他们都怎么实现功能。首先是这些道具都直接和人物属性挂钩,那么有人会想,是不是会要操作具体的人物属性,那是必须的,至于怎么操作,我们用到了数字账号,在客户端和服务器端通信,我们客户端有一个默认的数字账号,根据此账号来控制玩家的基本信息,如果账号有误服务器是拒绝操作的,所以改内存修改这个网络游戏的话也是行不通的。那我们怎么通过方式来更新服务器和客户端的资源同不能,我们采取了玩家主动请求的方式和异步接受服务器更新资料的方式,服务器定时给客户端发送资料,并强行更新本地资源,玩家也可以主动获取资源,所以这样就可以方便的同步最新的玩家信息,资料。

下面我们看一下使用一个道具试试!

移动终端网页游戏移植研发框架【道具系统】

注意看圈起来的几个点,首先这个物品的功效是加精血上限值10点,那么我们在使用前注意一下精血值为320,然后我们要做到使用之后,精血值的提升!!

玩家点击使用后,服务器端还要做很多操作来同步客户端数据,并且扣除该道具。

移动终端网页游戏移植研发框架【道具系统】

使用成功之后会有提示信息、

移动终端网页游戏移植研发框架【道具系统】OK,当玩家使用物品之后果然起到了即时的效果,客户端得精血值立刻就改变成为了330.这样一来,我们的其他操作就更方便了。

相当于,大的东西做完了,小的逻辑也肯定没问题,剩下就是道具的丢弃,和贩卖,需要注意的是,贩卖的时候需要得到物品道具的贩卖金钱,给予玩家提示,如图:

移动终端网页游戏移植研发框架【道具系统】

而且特别这类似重要物品需要给玩家提示,是否要丢弃,是否要贩卖,不然,一个不小心,点丢掉了,那不是给玩家带来损失了么?所以人性化的设计理念更为重要!

好了,下次和大家说一下聊天系统!如果你对我们的游戏感兴趣,可以加入我们的研发群一起讨论,策划游戏制作:45578308;

 

分类: 未分类 标签:

Unity3D Applying Texture – Model turns black

2012年3月5日 没有评论

I am following a course to learn Unity3D.

Game Development for iPhone/iPad Using Unity iPhone Tutorials

http://www.vtc.com/products/Game-Development-for-iPhone-iPad-Using-Unity-iPhone-Tutorials.htm

I am following along whatever author is doing on the screen. He is using Unity 1.6 and I am using Unity 3.40f5

When I try to apply the texture as he does in the movie, my model turns black. Is there something trivial that I am missing here?

Also find the screenshot attached.

  1. Whats happening in the movie with author – Unity3D Applying Texture - Model turns black

  2. Whats happening on my screen – Unity3D Applying Texture - Model turns black

It’s hard to tell from screen grabs but your material looks correct, assuming it says “Bumped Diffuse” after shader, I can’t tell.

When you first drag your model the scene, before applying a texture, it should self shade. If it doesn’t, you need to regenerate your model’s normals by clicking on the model and then in the inspector look for “Normals and Tangents.” After Normals choose “Calculate” the click “Apply” at the bottom, see what happens. I don’t know your model type but Unity has given me trouble in the past with Wavefront .obj files predefining their normals.

The other possible issue is a faulty UV import. If the tutorial is from v1.6 it is possible the model included with the tutorial isn’t importing correctly. I’ve had a similar issue where the UV’s were all set to ‘0 0′ so only the lowest corner pixel of my texture was used. Unity can’t do anything for you there. You can test this by creating a new material. Set the shader to diffuse. Set ‘Base(RGB)’ texture to ‘none’, and set ‘Main Color’ to something like blue. Apply it to your model. If you don’t define a texture then your model should appear blue. If it does, it means you likely have a UV import problem.

You just create the material as well but I think you did not import it to the object.

分类: stackoverflow精选, unity3d 标签:

移动终端网页游戏移植研发框架【精灵系统-纸娃娃】

2012年3月2日 没有评论

这下到了说精灵系统纸娃娃的时候了,在每款RPG游戏中都有类似的实体人物造型在游戏中呈现,当然呈现的方式不同,有可移动的,固定的。一般有两种模式,NPC人物,主角人物等类型,就是精灵系统的衍生,人物主角可移动的情况,和第一人称移动的,在我们这个游戏中,我不探讨人物移动【4方向,8方向】的精灵系统,我们做的是表现形式的NPC人物精灵系统,它拥有的功能就是【左右翻转,动态,说话,战斗】,在canvas android中我们利用到  Bitmap 绘制图像,控制素材的反转效果。

下面先在xml制作布局:

移动终端网页游戏移植研发框架【精灵系统-纸娃娃】

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<LinearLayout android:orientation="vertical"
		android:layout_height="180dip" android:layout_width="150dip"
		android:gravity="center">

		<TextView android:layout_height="wrap_content" android:text="npcname"
			android:id="@+id/npcname" 
			style="@style/GameText"
			android:gravity="center"
			android:textColor="#FFCC00"
			android:textSize="11dip"
			android:background="@drawable/js_npc_textbd"
			android:layout_width="wrap_content" />
		<ImageView android:layout_width="150dip" android:id="@+id/npcimg"
			android:layout_height="150dip" />
	</LinearLayout>
</LinearLayout>

定义好之后就开始将NPC制作成精灵控件!

Timer timer = new Timer();
	private int i = 0;
	private int cutnum;
	private String npcname;
	private String npcurl;
	private String npcimgrul;
	private Context context;
	private Bitmap npcbitmap;
	private Boolean npcflag=false;
	private String monsetid;
	public String getMonsetid() {
		return monsetid;
	}

	public void setMonsetid(String monsetid) {
		this.monsetid = monsetid;
	}
	public TextView npcnametext;
	private ArrayList<Bitmap> NpcImgResList;
	public ImageView npcimg;
	NpcBody npcbody = new NpcBody();
	public NpcView(Context context) {
		super(context);
		this.context=context;
	}
	
	public NpcView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context=context;
	}
	
	public NpcView(Context context, AttributeSet attrs,String npcname,String npcimgrul,int cutnum,Boolean npcflag,String monsetid) {
		super(context, attrs);
		this.context=context;
		initMonster(npcname, npcimgrul, cutnum,npcflag,monsetid);
	}
	
	private void initMonster(String npcname2, String npcimgrul, int cutnum2,Boolean npcflag,String monsetid) {
		// TODO Auto-generated method stub
		this.npcname=npcname2;
		this.npcimgrul=npcimgrul;
		this.cutnum=cutnum2;
		this.npcflag= npcflag;
		setMonsetid(monsetid);
		forceInflate();
		
	}

	public void initNpc(String npcname,String npcurl,int cutnum) {
		this.npcname=npcname;
		this.npcurl=npcurl;
		this.cutnum=cutnum;
		/*npcbitmap = BitmapFactory.decodeResource(this.getResources(),
				npcimgid);*/
		NpcImgResList =npcbody.getNpcBody(cutnum, npcurl);
		forceInflate();
	}
	
	public void forceInflate() {
		onFinishInflate();
	}
	
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		LayoutInflater li = LayoutInflater.from(getContext());
		li.inflate(R.layout.view_npc, this);
		
		if(npcflag!=true)
		{
		    internalOnFienishinflated();
		}
		else
		{
			internalOnFienishinflated2();
		}
	}
	public LayoutParams lp ;
	
	private void internalOnFienishinflated() {
		npcnametext = (TextView)findViewById(R.id.npcname);
		npcimg =(ImageView)findViewById(R.id.npcimg);
		npcnametext.setText(npcname);

		onplay();
	}
	private void internalOnFienishinflated2() {
		npcnametext = (TextView)findViewById(R.id.npcname);
		npcimg =(ImageView)findViewById(R.id.npcimg);
		npcnametext.setText(npcname);
		if(npcimgrul.length()>0)
		{
		   setMonsterImage(npcimgrul);
		}
	}

	private void setMonsterImage(String faceUrl) {
		LocalCache.getInstance(CacheValue.GameDataPack).useDownloadResource(faceUrl, new Action<CacheResult>() {
			@Override
			public void execute(CacheResult cacheResult) {
				if(cacheResult.isCached()) {
					String path = cacheResult.getCachedPath();
					final Bitmap bm = BitmapCache.Instance.getFileImageOrCache(path);
					TApp.getActivity().runOnUiThread(new Runnable() {
						@Override
						public void run() {
							BitmapDrawable drwawable = new BitmapDrawable(bm);
							npcimg.setBackgroundDrawable(drwawable);	
							
						}
					});
				}
			}
		});
	}

 

然后利用动画播放的机制,将帧显示出来,这样纸娃娃系统就基本成型了,而且能够动起来了。而且还可以拓展,这个就靠大家发挥了。

下面我贴一下制作成功的精灵系统在地图系统中的显示效果。

移动终端网页游戏移植研发框架【精灵系统-纸娃娃】

这就是我们游戏的城池场景,里面的NPC都是非常精美的。

移动终端网页游戏移植研发框架【精灵系统-纸娃娃】

这个就是我们的练级地图了,这套地图系统是由服务器配置的,怪物的坐标,朝向,动作,对话,都可以在服务器端配置。

游戏群:【45578308】欢迎进群讨论

分类: 未分类 标签:

Accessing Objects in other Layers (cocos2d)

2012年3月1日 没有评论

I was playing around with a Joystick moving a Sprite around in one layer. Now, according to best practice, the Joystick and the Sprite have to be in different Layers of the same scene. I have managed to separate these, yet I am now completely stuck having absolutely no clue whatsoever how to pass joystick commands from one layer to another? What is the recommended way to do this?

Scene

  • Game Play Layer
    • Sprite
  • Game Control Layer
    • Joystick

When the joystick is manipulated I need to pass this info to the GamePlayLayer to control the sprite.

Well, I got a great Cocos2d book, written by Rod Strougo and Ray Wenderlich, by the name “Learning Cocos2d”. In their book, they implement a game, which has a joystick implemented and all, using your initial setup. The GamePlayLayer contains both the joyStick and the hero sprite. (See book page 40).

I don’t believe they would use bad practices in their book, given they are very talented!

With that being said, I have possible solutions, if you wish to implement them on separate layers:

GameScene
|
|__>GameLayer
|
|__>ControlLayer

That’s your basic setup. But, intuitively, what is the purpose of the control layer? Control the game layer’s content! So, I would suggest you hold a (weak) reference to the GameLayer within the ControlLayer. That way, using a simple:

@property (nonatomic, assign) CCSprite* hero;

you now have access to the hero from the ControlLayer!

Extra (if needed):

//GameScene init:
- (id)init {
    ....
    gameLayer = [GameLayer node];
    controlLayer = [ControlLayer node];
    [controlLayer setGameLayerRef:gameLayer];
    ...
}

// Control layer:
@property (nonatomic, assign) GameLayer* gameLayerRef;

Even though I just suggested that way, I don’t use it in my games :)

What I normally do is:

Make the GameScene class a “Semi-Singleton”. (I learned this method from “Learn iPhone and iPad Game Dev” By Itterheim (aka gaming horror, Kobold2d publisher … etc).

Then, inside the control layer, I would call the GameScene object:

[[GameScene sharedScene] doSomethingToTheGameLayer];

Yeah, the gameScene has simplistic methods that just relies what the control need to update in the game layer.


Edit:

Implementing the Semi-singleton pattern, as described by Itterheim in his book.

But, what is semi-singleton?

It has the singleton pattern’s property: you can access the object instance from anywhere using a static call.

[GameScene sharedScene];

However, singleton objects are usually retained, after being created for the first time, till the end of the application’s life. In the Semi-singleton pattern, this is not the case.

Once you create the instance, you cannot create another instance before destroying the old one, BUT once you are done with the instance, you destroy it (dealloc). Creating another one when necessary.

Recap:
Semi-Singleton: Create many object from it, but only one at any given time. Only recreate after destroying the old.

Implementation:

Of course, as you do with any singleton class, you first declare a static variable of the same type of the class:

//In GameScene.m
static GameScene* instance = nil;

@implementation

//Here we have the static method to access the instance:
+(GameScene*)sharedScene {
    //you must have created one before trying to access it "Globally".
    ///Typically, created where you transition the GameScene using CCDirector's replaceScene.
    NSAssert(instance != nil, @"GameScene not instantiated!!");
    return instance;
}

-(id)init {
    if((self = [super init])) {
        //Make sure you don't have another instance of the class created
        //NOTE: Possible race condition that I wouldn't worry about, since it should never happen.
        NSAssert(instance == nil, @"Another instance is already created!!");
        instance = self;

        ...
    }
    return self;
}

//Don't forget!! Dealloc!!
- (void)dealloc {
    //the only instance we had is dealloc'd! We are back to zero. Can create a new one later! :D
    instance = nil;
    [super dealloc];
}

Edit2:

So, the timeline:

CCScene* scene = [GameScene node];
[[CCDirector sharedDirector] replaceScene:scene];
...
[[GameScene sharedScene] doSomething];
...
[[CCDirector sharedDirector] replaceScene:otherScene];
//After the new scene replaces GameScene, dealloc will be called, implicitly. Making instance = nil;
instance = nil;
[super dealloc];
...
//Loop again
CCScene* scene = [GameScene node];
[[CCDirector sharedDirector] replaceScene:scene];
...
分类: cocos2d, stackoverflow精选 标签:

移动终端网页游戏移植研发框架【客户端战斗系统】

2012年3月1日 没有评论

     传统网页游戏中的战斗系统无非两种,服务器端请求数据资源后,在游戏中进行配置,然后以动画形式表现出来。诸如十年一剑这类网游,战斗系统就是,靠装备+技能配置+家将辅助。在这里我想说决定一款游戏是否好玩,关键就在2个地方,游戏性【新颖的系统,和各种创新玩法】和交互性。所以我们除了要有研发游戏技术,还要有研发游戏的点子。做出什么样的系统才能吸引玩家?我们的游戏中,战斗系统算是一个小亮点,和大多文字类型游戏一样,通过玩家请求打怪,获得打怪数据,只不过将打怪数据图层化,界面化。

    下面我介绍一下我们游戏里面的战斗系统结构和框架:

    首先是视图:

    由于是在手机界面上,手机的屏幕大小是我们做游戏最大的局限,有非常好的场景和美工,但缺无处施展开来!所以我在做战斗系统的时候将地图背景区域化,局部显示,然后利用android手机滑动特性,让然家自由查看战斗场景中的每一个细节部分!

移动终端网页游戏移植研发框架【客户端战斗系统】

这使我们战斗系统中的战斗背景图,很明显中间的竞技台就是玩家们厮杀的战场!我们要将玩家和怪物实体化,将玩家的造型,和怪物的造型实例化出来。简单的看一下游戏中的制作界面,和需求:

     在战斗界面中 需要有

    1人物造型

    2人物属性,包括血条显示,属性值显示

    3人物技能展示

    4战斗信息框

    这4个部分就构成了一个完整的整个战斗系统。

移动终端网页游戏移植研发框架【客户端战斗系统】

最后就是详细说一下我们的技能显示,这点也是整个游戏中的一大玩点。首先详细秒速一下绿色背景区域,就是我们的技能显示区域,技能显示展示方法我们不是用andorid的控件和工具,我们是自己做的一套帧动画播放机制,android JAVA里面的Timer 使我们技能发招的大功臣!

 Timer timer ;
    Runnable runanble;
	private int j = 0;
    //技能播放
    public void onplay(final String nowskillname,final String nowlife,final Boolean nowpkdxflag) {
    	timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				nowSkillName =nowskillname;
				nowLife=nowlife;
				nowPKdxflag = nowpkdxflag;
				j++;
				Message mesasge = new Message();
				mesasge.what = j;

				if(j<=5)
				{
					playerhandler.sendMessage(mesasge);	
					
				}
				else
				{
					j=0;
					timer.cancel();
					close_Skill();
					playerhandler.removeMessages(j);
				}
			}
		}, 0, 200);
	}
	public class DelayThread extends Thread {
		int milliseconds;

		public DelayThread(int j) {
			milliseconds = j;
		}

		public void run() {                                                                                                                                                                                                                                                                                                                 
			while (true) {
				try {
					sleep(milliseconds);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				playerhandler.sendEmptyMessage(0);
			}
		}
	}
	private Handler playerhandler = new Handler() {
		@Override
		public void handleMessage(final Message msg) {
			TApp.getActivity().runOnUiThread(new Runnable() {
				@Override
				public void run() {
						//释放技能
				}
			});
		}
	};

 然后通过线程来跑技能释放动画,动画取材思路我就不说了,我们的算法就是帧组合,取出不同帧来呈现。

   最后说一下数据结构,通过以上的模块,组合起来的战斗效果只能说达到了高仿实景PK的界面,但是流畅度和画面的展现形式还有待提高的。

   下面展现一下最新的一组战斗图片:

   我们通过山河社稷图找到地图上的练级地图,进入1-10级地图:

   

移动终端网页游戏移植研发框架【客户端战斗系统】

   之后进入地图场景,场景上面的怪物和NPC都是流畅可见的。怪物和NPC其实目前其实就是精灵系统,现在精灵系统上面的元素还比较少,不过要是做动作,对话,还是可以简单实现的。

   

移动终端网页游戏移植研发框架【客户端战斗系统】

  最后就是点击怪物,然后弹出战斗提示,进入战斗场景!!开始战斗!!

  

移动终端网页游戏移植研发框架【客户端战斗系统】

移动终端网页游戏移植研发框架【客户端战斗系统】

移动终端网页游戏移植研发框架【客户端战斗系统】

这就是整个战斗系统的具体流程,及游戏的玩法!!从界面效果上看,基本上是能达到实景界面PK的模式,而且通过局部显示,玩家可以查看战斗中的每一个场景点。

如果有喜欢我们这款游戏的朋友,可以加群【剑神客栈研发组:45578308】。一起讨论,策划游戏!

分类: 未分类 标签: