关于碰撞检测/About collision detection
Posted: Fri Jan 18, 2013 7:21 pm
当我成功的完成了我的碰撞检测算法后,真心想跟大家分享一下,希望大家多给些意见,让这个算法更加完善。
首先解释一下代码中用到的变量:
$0D $0E $14 $15 $16 $17 $18 $19 (Sp_addr1~Sp_addr4)
这八个内存里面分别保存了4个ROM区的16位内存地址(低8为+高8位),用来记录player精灵当前所在的位置(最少占1格,最多占4格)。
思路就是将精灵的位置映射到地图中,地图数据保存在命名表,命名表的数据又是从ROM中提取出来的,所以直接将精灵的位置映射到ROM了。
$13 $0F (Xp,Yp)
分别保存了精灵的水平和垂直的偏移量(值都是在F9~07间变化)。当精灵在某个方向上移动时,每8像素后便完全进入了另一个tile,所以这两个偏移量将会区分精灵是从上下左右哪个方向进入tile。而从不同的方向进入将会有不同的方法改变精灵当前在ROM中映射的内存地址。
代码中用到的方法:
change_addr()
当精灵从不同的方向完全进入一个tile的时候(通过对Xp,Yp的值来进行判断),它在ROM中所映射的地址将会有所改变(用以对未来前进方向是否可以通行进行判断)。
xx_on()
对应四个按钮的触发事件。
get(Sp_addr)
获取精灵当前映射到的地址。
getID(Sp_addr)
获取精灵所映射的地址中保存的tile ID。
=========================
代码:
//==================
change_addr(){
if(Xp==0 && Yp!=0){
if(Yp>8){
Sp_addr2=Sp_addr1+$20
}
if(Yp<8){
Sp_addr2=Sp_addr1-$20
}
}
if(Xp!=0 && Yp==0){
if(Xp>8){
Sp_addr2=Sp_addr1+$1
}
if(Xp<8){
Sp_addr2=Sp_addr1-$1
}
}
}
//================
//===================
Up_on(){
change_addr();
if(Yp==$07){
Sp_addr1-=$20;
Yp=$00;
Sy--;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1-$20;
if((getID(Sp_addr2)-$82)<0){
Yp++;
Sy--;
return;
}else{
return;
}
}
if(Xp==0 && Yp!=0){
Yp++;
Sy--;
return;
}
if(Xp!=0 && Yp==0){
get(Sp_addr1);
Sp_addr3=Spaddr_1-$20;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2-$20;
if((getID(Sp_addr4)-$82)<0){
Yp++;
Sy--;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Yp++;
Sy--;
return;
}
}
//===================
//====================
Down_on(){
change_addr();
if(Yp==$F9){
Sp_addr1+=$20;
Yp=$00;
Sy++;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1+$20;
if((getID(Sp_addr2)-$82)<0){
Yp--;
Sy++;
return;
}else{
return;
}
}
if(Xp==0 && Yp!=0){
Yp--;
Sy++;
return;
}
if(Xp!=0 && Yp==0){
get(Sp_addr1);
Sp_addr3=Spaddr_1+$20;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2+$20;
if((getID(Sp_addr4)-$82)<0){
Yp--;
Sy++;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Yp--;
Sy++;
return;
}
}
//======================
//======================
Left_on(){
change_addr();
(Xp==$07){
Sp_addr1-=$01;
Xp=$00;
Sx--;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1-$01;
if((getID(Sp_addr2)-$82)<0){
Xp++;
Sx--;
return;
}else{
return;
}
}
if(Xp!=0 && Yp==0){
Xp++;
Sx--;
return;
}
if(Xp==0 && Yp!=0){
get(Sp_addr1);
Sp_addr3=Spaddr_1-$01;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2-$01;
if((getID(Sp_addr4)-$82)<0){
Xp++;
Sx--;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Xp++;
Sx--;
return;
}
}
//======================
//======================
Right_on(){
change_addr();
(Xp==$F9){
Sp_addr1+=$01;
Xp=$00;
Sx++;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1+$01;
if((getID(Sp_addr2)-$82)<0){
Xp--;
Sx++;
return;
}else{
return;
}
}
if(Xp!=0 && Yp==0){
Xp--;
Sx++;
return;
}
if(Xp==0 && Yp!=0){
get(Sp_addr1);
Sp_addr3=Spaddr_1+$01;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2+$01;
if((getID(Sp_addr4)-$82)<0){
Xp--;
Sx++;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Xp--;
Sx++;
return;
}
}
//======================
首先解释一下代码中用到的变量:
$0D $0E $14 $15 $16 $17 $18 $19 (Sp_addr1~Sp_addr4)
这八个内存里面分别保存了4个ROM区的16位内存地址(低8为+高8位),用来记录player精灵当前所在的位置(最少占1格,最多占4格)。
思路就是将精灵的位置映射到地图中,地图数据保存在命名表,命名表的数据又是从ROM中提取出来的,所以直接将精灵的位置映射到ROM了。
$13 $0F (Xp,Yp)
分别保存了精灵的水平和垂直的偏移量(值都是在F9~07间变化)。当精灵在某个方向上移动时,每8像素后便完全进入了另一个tile,所以这两个偏移量将会区分精灵是从上下左右哪个方向进入tile。而从不同的方向进入将会有不同的方法改变精灵当前在ROM中映射的内存地址。
代码中用到的方法:
change_addr()
当精灵从不同的方向完全进入一个tile的时候(通过对Xp,Yp的值来进行判断),它在ROM中所映射的地址将会有所改变(用以对未来前进方向是否可以通行进行判断)。
xx_on()
对应四个按钮的触发事件。
get(Sp_addr)
获取精灵当前映射到的地址。
getID(Sp_addr)
获取精灵所映射的地址中保存的tile ID。
=========================
代码:
//==================
change_addr(){
if(Xp==0 && Yp!=0){
if(Yp>8){
Sp_addr2=Sp_addr1+$20
}
if(Yp<8){
Sp_addr2=Sp_addr1-$20
}
}
if(Xp!=0 && Yp==0){
if(Xp>8){
Sp_addr2=Sp_addr1+$1
}
if(Xp<8){
Sp_addr2=Sp_addr1-$1
}
}
}
//================
//===================
Up_on(){
change_addr();
if(Yp==$07){
Sp_addr1-=$20;
Yp=$00;
Sy--;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1-$20;
if((getID(Sp_addr2)-$82)<0){
Yp++;
Sy--;
return;
}else{
return;
}
}
if(Xp==0 && Yp!=0){
Yp++;
Sy--;
return;
}
if(Xp!=0 && Yp==0){
get(Sp_addr1);
Sp_addr3=Spaddr_1-$20;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2-$20;
if((getID(Sp_addr4)-$82)<0){
Yp++;
Sy--;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Yp++;
Sy--;
return;
}
}
//===================
//====================
Down_on(){
change_addr();
if(Yp==$F9){
Sp_addr1+=$20;
Yp=$00;
Sy++;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1+$20;
if((getID(Sp_addr2)-$82)<0){
Yp--;
Sy++;
return;
}else{
return;
}
}
if(Xp==0 && Yp!=0){
Yp--;
Sy++;
return;
}
if(Xp!=0 && Yp==0){
get(Sp_addr1);
Sp_addr3=Spaddr_1+$20;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2+$20;
if((getID(Sp_addr4)-$82)<0){
Yp--;
Sy++;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Yp--;
Sy++;
return;
}
}
//======================
//======================
Left_on(){
change_addr();
(Xp==$07){
Sp_addr1-=$01;
Xp=$00;
Sx--;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1-$01;
if((getID(Sp_addr2)-$82)<0){
Xp++;
Sx--;
return;
}else{
return;
}
}
if(Xp!=0 && Yp==0){
Xp++;
Sx--;
return;
}
if(Xp==0 && Yp!=0){
get(Sp_addr1);
Sp_addr3=Spaddr_1-$01;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2-$01;
if((getID(Sp_addr4)-$82)<0){
Xp++;
Sx--;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Xp++;
Sx--;
return;
}
}
//======================
//======================
Right_on(){
change_addr();
(Xp==$F9){
Sp_addr1+=$01;
Xp=$00;
Sx++;
return;
}
if(Xp==0 && Yp==0){
get(Sp_addr1);
Sp_addr2=Spaddr_1+$01;
if((getID(Sp_addr2)-$82)<0){
Xp--;
Sx++;
return;
}else{
return;
}
}
if(Xp!=0 && Yp==0){
Xp--;
Sx++;
return;
}
if(Xp==0 && Yp!=0){
get(Sp_addr1);
Sp_addr3=Spaddr_1+$01;
if((getID(Sp_addr3)-$82)<0){
get(Sp_addr2);
Sp_addr4=Spaddr_2+$01;
if((getID(Sp_addr4)-$82)<0){
Xp--;
Sx++;
return;
}else{
return;
}
}else{
return;
}
}
if(Xp!=0 && Yp!=0){
Xp--;
Sx++;
return;
}
}
//======================