用JavaScript编码2D游戏物理,不平坦的地面和旋转

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用JavaScript编码2D游戏物理,不平坦的地面和旋转相关的知识,希望对你有一定的参考价值。

我在网络编程课程中有一个小项目,我应该用javascript做一个小游戏。这是游戏:两门大炮固定在游戏空间的相对两端。大炮轮流互相射击,玩家将大炮倾斜到一定程度,并选择一种用来射击大炮的力。如果有时间,我会考虑添加很多其他内容。

[我找到了一个不错的网站http://www.rodedev.com/tutorials/gamephysics/,让我着手进行2D物理学,并进行了一些测试,请参见下面的代码。但是,我确实有两个大问题:

  1. 非平坦的地面/地面。
  2. 旋转!

目前,脚本仅检查floorDiv的style.top值,因此该框将始终“降落”在此像素行上。如果我想拥有高度可变的地形,这是不够的。你们有什么想法可以做到这一点?无论如何,有没有检查特定像素的颜色?如果是这样,我可以检查非天空或地面彩色像素,并将其设置为着陆标准。

我需要旋转大炮,以便玩家可以调整目标!我想我将制作两个不同的加农炮对象:“基地”加农炮和加农炮桶。然后,当玩家按下一个键时,我可以旋转炮管。不幸的是,轮换似乎很难进行网络编程。我在http://code.google.com/p/jquery-rotate/处找到了这个jquery插件,但是我没有完全按照我的意愿运行它。即使我已确定炮弹在图片中居中,也存在一些平移,而不仅仅是旋转。我想这可能是因为图片没有围绕其中心旋转吗?请参见下面的旋转测试代码(您必须下载旋转插件(如果您想尝试代码)。我想我可以为每个角度拍一张照片,但这似乎有点浪费因为否则大炮没有实际的视觉变化。

[此外,如果我想同时对多个对象进行动画处理,您是否认为我应该只在同一gameloop函数中更改所有对象?有任何想法吗?

以下是物理测试的代码

CSS文件

#moveDiv 
    position:absolute;
    width:100px;
    height:100px;
    background-color:#000;


#floorDiv 
    position:absolute;
    width:800px;
    height:1px;
    background-color:#2E2;


table 
text-align:right;


table input 
    width:35px;

html文件

<script type="text/javascript">
//global vars
var gravity = 0.5;
var friction = 0.5;
var moving = false;
var moveDiv;
var floorDiv;
var yPos;
var xPos;
var floorPos;
var velocity_y = 0;
var velocity_x = 0;
</script>
</head>

<body onload="initialize();">
<input type="button" value="fall" onclick="fall();"></button>
<input type="button" value="Push" onclick="push();"></button>
<input type="button" value="reset" onclick="reset();"></button>

<table>
<tr>
<td>Angle: <input type="text" value="45" id="angle" /></td>
<td>Speed: <input type="text" value="10" id="speed"/></td>
</tr>
<tr>
<td>Gravity: <input type="text" value="0.5" id="gravity" /></td>
<td>Friction: <input type="text" value="0.5" id="friction" /></td>
</table>

<div id="moveDiv"></div>
<div id="floorDiv"></div>
</body>
</html>

js文件

function initialize() 
    moveDiv = document.getElementById('moveDiv');
    floorDiv = document.getElementById('floorDiv'); 

    moveDiv.style.left=400;
    moveDiv.style.top=50;

    floorDiv.style.left=200;
    floorDiv.style.top=400;
//end initialize

function fall() 

    moving=true;
    var angle = 275;
    var rad = angle / (Math.pi * 2);
    var scale_x = Math.cos(rad);
    var scale_y = Math.sin(rad);

    var moveDivSpeed = 0;

    gameLoop();

//end fall

function push() 

    moving=true;
    var angle = document.getElementById('angle').value;
    var rad = angle / (Math.PI * 2);
    var scale_x = Math.cos(rad);
    var scale_y = Math.sin(rad);
    var moveDivSpeed = document.getElementById('speed').value;
    friction = document.getElementById('friction').value;
    gravity = document.getElementById('gravity').value;
    velocity_x = moveDivSpeed*scale_x;
    console.log("original velocity_x is " + velocity_x);
    velocity_y = moveDivSpeed*scale_y;
    gameLoop();


function gameLoop () 
    //console.log("gameLoop start");
    var len = moveDiv.style.top.length;
    var presentTop = parseInt(moveDiv.style.top.substr(0, len-2));

    var lenX = moveDiv.style.left.length;
    var presentLeft = parseInt(moveDiv.style.left.substr(0, lenX-2));

    var len2 = floorDiv.style.top.length;
    var floorTop = parseInt(floorDiv.style.top.substr(0, len2-2));

    if (moving == true) 
    
        velocity_y -= gravity;

        if ((presentTop+100) - velocity_y < floorTop) 
         //if moveDiv hasn't hit the floor yet...
            moveDiv.style.top = presentTop - velocity_y;
            moveDiv.style.left = presentLeft + velocity_x;
        
        else if (presentTop + 100 == floorTop) //if moveDiv is ON the floor
        
            velocity_x = velocity_x*(1-friction);
            moveDiv.style.left = presentLeft + velocity_x;
            console.log("on the floor");
            console.log("friction is " + friction);
            console.log(" and velocity_x is " + velocity_x);
            console.log("moveDiv.style.left is " +moveDiv.style.left);

            if (velocity_x <= 1)
            
                console.log("stopped moving");
                moving = false;
            

        
        else //if moveDiv will hit the floor/go through the floor this time
        
            var diff = floorTop - (presentTop + 100);
            moveDiv.style.top = presentTop + diff;
            moveDiv.style.left = presentLeft + velocity_x;
        
    
    else if (moving == false) 
    
        clearTimeout(runAgain);
        console.log("else if moving == false");
        return false;
    

    var runAgain = setTimeout("gameLoop()", 5);
    //console.log("end of gameLoop");
    return false;
//end gameLoop

function reset () 
    moving = false;

    moveDiv.style.left=400;
    moveDiv.style.top=50;

    floorDiv.style.left=200;
    floorDiv.style.top=400;
//end reset

旋转测试的代码(只是html文件和旋转插件)

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="jquery.rotate.1-1.js"></script>
<script type="text/javascript">
    $(document).ready(function() 

        $("#hide").click(function() 
            $("p").hide(500);
            $(".box").animate(height:300, opacity:0, 1000);
        );

        $("#show").click(function() 
            $("p").show(500);
            $(".box").animate(height:100, opacity:100, 1000);
        );

        $(".box").mouseenter(function() 
            $(".box").animate(height:300, opacity:0, 500);
        );

        $(".box").mouseleave(function() 
            $(".box").animate(height:100, opacity:10, 1000);
        );

        $("#move").click(function() 
            $("#grey").animate(left: -300, top: -100, 1000)
            .animate(left: -600, top: 200, 1000);
        );

        $("#cannonball").click(function() 
            $("#cannonball").animate("left": "+=300", "top": "-=100", 500)
            .animate("left": "+=300", "top": "+=100", 500);

        );

        $("p.fading").css("opacity","0.3");
        $("p.fading").hover(function() 
            $(this).stop().animate(opacity: 1.0, "slow");, 
                function () 
                $(this).stop().animate(opacity: 0.3, "slow");
            );

        $("#rotateRight").click(function() 
            $("#cannonball").rotate(10);
        );

    ); //end jquery document.ready scripts

function initialize () 
    document.getElementById('box').style.top = 250;

</script>

<style type="text/css">
body 
    background-color: #ccc;


.box 
    background-color: #000;
    width:100px;
    height:100px;
    margin-left:300px;


.divMove 
    position:relative;
    top:350px;
    float:right;
    background-color: #ddd;
    width:100px;
    height:100px;
    margin-right:100px;
   

#cannonball 
    position: relative;

</style>
</head>
<body onload="initialize();">
<p>Let's make this disappear and appear.</p>

<button id="hide">Hide</button>
<button id="show">Show</button>
<button id="move">Move</button>
<button id="rotateRight">Rotate+</button>

<div id="box" class="box">
</div>


<div class="divMove" id="grey">
</div>

<img src="http://dl.dropbox.com/u/18833130/Webprogrammering/test/cannonball.png" id="cannonball" border="1" />
<p class="fading">This is a paragraph that fades. Let's see how it looks.</p>
</body>
</html> 

我为冗长的帖子和大量的代码表示歉意,但是,如果您想尝试一下,基本上可以复制粘贴,我认为这样讨论会更容易!

答案

我想我将制作两个不同的加农炮对象,加农炮“基地”和加农炮枪管。然后,当玩家按下一个键时,我可以旋转炮管。不幸的是,轮换似乎很难进行网络编程。

最简单(现在)是使用CSS transform property

transform

[此外,如果我想同时对多个对象进行动画处理,您是否认为我应该只在同一gameloop函数中更改所有对象?有任何想法吗?

对于应该可以正常工作的简单实现。

以上是关于用JavaScript编码2D游戏物理,不平坦的地面和旋转的主要内容,如果未能解决你的问题,请参考以下文章

Cocos2d-x 3.0中 物理碰撞检測中onContactBegin回调函数不响应问题

coco2d-x 3.0游戏实例学习笔记 《跑酷》 第二步---游戏界面&amp;全新的3.0物理世界

Egret中使用P2物理引擎

Unity2D游戏物理引擎演示

带有内部 box2d 物理崩溃的 SpriteKit 游戏

Unity 2D精灵(Sprite)与2D物理组件