我正在研究等距游戏引擎,并且已经创建了一个用于像素完美点击检测的算法。访问 project并注意点击检测能够检测到瓷砖的哪个边缘被点击。它还检查 y-index 以单击最前面的图块。
我当前算法的解释:
等距网格由 100*65px 的平铺图像组成。TileW=100, TileL=50, tileH=15

map 由一个三维数组 map[z][y][x] 表示.
瓷砖中心点 (x,y)是这样计算的:
//x, y, z are the position of the tile
if(y%2===0) { x-=-0.5; } //To accommodate the offset found in even rows
this.centerX = (x*tileW) + (tileW/2);
this.centerY = (y*tileL) - y*((tileL)/2) + ((tileL)/2) + (tileH/2) - (z*tileH);

Tile.prototype.allContainsMouse = function() {
var dx = Math.abs(mouse.mapX-this.centerX),
dy = Math.abs(mouse.mapY-this.centerY);
if(dx>(tileW/2)) {return false;} //Refer to image
return (dx/(tileW*0.5) + (dy/(tileL*0.5)) < (1+tileHLRatio));
}
Tile.prototype.allContainsMouse()如果鼠标在绿色范围内,则返回 true。通过检查 dx > 瓷砖宽度的一半来裁剪红色区域
Tile.prototype.topContainsMouse = function() {
var topFaceCenterY = this.centerY - (tileH/2);
var dx = Math.abs(mouse.mapX-this.centerX),
dy = Math.abs(mouse.mapY-topFaceCenterY);
return ((dx/(tileW*0.5) + dy/(tileL*0.5) <= 1));
};

Tile.prototype.leftContainsMouse = function() {
var dx = mouse.mapX-this.centerX;
if(dx<0) { return true; } else { return false; }
};
Tile.prototype.rightContainsMouse = function() {
var dx = mouse.mapX-this.centerX;
if(dx>0) { return true; } else { return false; }
};
allContainsMouse()返回 true,map[z][y][x] 是我们鼠标所在的图块。 tilesUnderneathMouse大批。 tilesUnderneathMouse阵列,并选择最高y的瓦片.它是最前面的瓷砖。if(allContainsMouse && !topContainsMouse)

if(allContainsMouse && !topContainsMouse && leftContainsMouse)

y=mx+b 下方依赖于 tileX、tileY 近似值的线(近似方形网格)。最佳答案
这个答案基于:
//---------------------------------------------------------------------------
// tile sizes
const int cxs=100;
const int cys= 50;
const int czs= 15;
const int cxs2=cxs>>1;
const int cys2=cys>>1;
// view pan (no zoom)
int pan_x=0,pan_y=0;
//---------------------------------------------------------------------------
void isometric::cell2scr(int &sx,int &sy,int cx,int cy,int cz) // grid -> screen
{
sx=pan_x+(cxs*cx)+((cy&1)*cxs2);
sy=pan_y+(cys*cy/2)-(czs*cz);
}
//---------------------------------------------------------------------------
void isometric::scr2cell(int &cx,int &cy,int &cz,int sx,int sy) // screen -> grid
{
// rough cell ground estimation (no z value yet)
cy=(2*(sy-pan_y))/cys;
cx= (sx-pan_x-((cy&1)*cxs2))/cxs;
cz=0;
// isometric tile shape crossing correction
int xx,yy;
cell2scr(xx,yy,cx,cy,cz);
xx=sx-xx; mx0=cx;
yy=sy-yy; my0=cy;
if (xx<=cxs2) { if (yy> xx *cys/cxs) { cy++; if (int(cy&1)!=0) cx--; } }
else { if (yy>(cxs-xx)*cys/cxs) { cy++; if (int(cy&1)==0) cx++; } }
}
//---------------------------------------------------------------------------
我使用了您的布局(我花了一段时间将我的布局转换为它,希望我不会在某处犯一些愚蠢的错误):
cell2scr(x,y,0,0,0) 返回的坐标2对于这种情况(过去花很多时间弄清楚那个)。cell2scr很简单。屏幕位置是平移偏移 + 单元格位置乘以其大小(步长)。 x轴需要对偶数/奇数行进行更正(这就是 ((cy&1)*cxs2) 的用途)和 y轴由 z 移动轴 ( ((cy&1)*cxs2) )。我的屏有点(0,0)在左上 Angular ,+x轴指向右侧和 +y是向下。scr2cell由 cell2scr 的方程代数求解屏幕位置完成同时假设 z=0所以只选择网格地。最重要的是,如果鼠标位置在找到的单元格区域之外,则添加偶数/奇数校正。scr2cell(x,y,z,mouse_x,mouse_y)只返回鼠标在地面上的单元格。因此,如果您想添加当前的选择功能,您需要扫描该位置的顶部单元格和几个相邻的单元格,然后选择距离最小的单元格。
z轴大小 ( czs ),最大数量 z层( gzs )和像元大小( cys )。 C++ 我的扫描代码如下所示: // grid size
const int gxs=15;
const int gys=30;
const int gzs=8;
// my map (all the cells)
int map[gzs][gys][gxs];
void isometric::scr2cell(int &cx,int &cy,int &cz,int sx,int sy)
{
// rough cell ground estimation (no z value yet)
cy=(2*(sy-pan_y))/cys;
cx= (sx-pan_x-((cy&1)*cxs2))/cxs;
cz=0;
// isometric tile shape crossing correction
int xx,yy;
cell2scr(xx,yy,cx,cy,cz);
xx=sx-xx;
yy=sy-yy;
if (xx<=cxs2) { if (yy> xx *cys/cxs) { cy++; if (int(cy&1)!=0) cx--; } }
else { if (yy>(cxs-xx)*cys/cxs) { cy++; if (int(cy&1)==0) cx++; } }
// scan closest neighbors
int x0=-1,y0=-1,z0=-1,a,b,i;
#define _scann \
if ((cx>=0)&&(cx<gxs)) \
if ((cy>=0)&&(cy<gys)) \
{ \
for (cz=0;(map[cz+1][cy][cx]!=_cell_type_empty)&&(cz<czs-1);cz++); \
cell2scr(xx,yy,cx,cy,cz); \
if (map[cz][cy][cx]==_cell_type_full) yy-=czs; \
xx=(sx-xx); yy=((sy-yy)*cxs)/cys; \
a=(xx+yy); b=(xx-yy); \
if ((a>=0)&&(a<=cxs)&&(b>=0)&&(b<=cxs)) \
if (cz>=z0) { x0=cx; y0=cy; z0=cz; } \
}
_scann; // scan actual cell
for (i=gzs*czs;i>=0;i-=cys) // scan as many lines bellow actual cell as needed
{
cy++; if (int(cy&1)!=0) cx--; _scann;
cx++; _scann;
cy++; if (int(cy&1)!=0) cx--; _scann;
}
cx=x0; cy=y0; cz=z0; // return remembered cell coordinate
#undef _scann
}
这总是选择顶部单元格(所有可能的最高单元格)在使用鼠标时感觉正确(至少对我而言):
//---------------------------------------------------------------------------
//--- Isometric ver: 1.01 ---------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _isometric_h
#define _isometric_h
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// colors 0x00BBGGRR
DWORD col_back =0x00000000;
DWORD col_grid =0x00202020;
DWORD col_xside=0x00606060;
DWORD col_yside=0x00808080;
DWORD col_zside=0x00A0A0A0;
DWORD col_sel =0x00FFFF00;
//---------------------------------------------------------------------------
//--- configuration defines -------------------------------------------------
//---------------------------------------------------------------------------
// #define isometric_layout_1 // x axis: righ+down, y axis: left+down
// #define isometric_layout_2 // x axis: righ , y axis: left+down
//---------------------------------------------------------------------------
#define isometric_layout_2
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/*
// grid size
const int gxs=4;
const int gys=16;
const int gzs=8;
// cell size
const int cxs=100;
const int cys= 50;
const int czs= 15;
*/
// grid size
const int gxs=15;
const int gys=30;
const int gzs=8;
// cell size
const int cxs=40;
const int cys=20;
const int czs=10;
const int cxs2=cxs>>1;
const int cys2=cys>>1;
// cell types
enum _cell_type_enum
{
_cell_type_empty=0,
_cell_type_ground,
_cell_type_full,
_cell_types
};
//---------------------------------------------------------------------------
class isometric
{
public:
// screen buffer
Graphics::TBitmap *bmp;
DWORD **pyx;
int xs,ys;
// isometric map
int map[gzs][gys][gxs];
// mouse
int mx,my,mx0,my0; // [pixel]
TShiftState sh,sh0;
int sel_x,sel_y,sel_z; // [grid]
// view
int pan_x,pan_y;
// constructors for compiler safety
isometric();
isometric(isometric& a) { *this=a; }
~isometric();
isometric* operator = (const isometric *a) { *this=*a; return this; }
isometric* operator = (const isometric &a);
// Window API
void resize(int _xs,int _ys); // [pixels]
void mouse(int x,int y,TShiftState sh); // [mouse]
void draw();
// auxiliary API
void cell2scr(int &sx,int &sy,int cx,int cy,int cz);
void scr2cell(int &cx,int &cy,int &cz,int sx,int sy);
void cell_draw(int x,int y,int tp,bool _sel=false); // [screen]
void map_random();
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
isometric::isometric()
{
// init screen buffers
bmp=new Graphics::TBitmap;
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
pyx=NULL; xs=0; ys=0;
resize(1,1);
// init map
int x,y,z,t;
t=_cell_type_empty;
// t=_cell_type_ground;
// t=_cell_type_full;
for (z=0;z<gzs;z++,t=_cell_type_empty)
for (y=0;y<gys;y++)
for (x=0;x<gxs;x++)
map[z][y][x]=t;
// init mouse
mx =0; my =0; sh =TShiftState();
mx0=0; my0=0; sh0=TShiftState();
sel_x=-1; sel_y=-1; sel_z=-1;
// init view
pan_x=0; pan_y=0;
}
//---------------------------------------------------------------------------
isometric::~isometric()
{
if (pyx) delete[] pyx; pyx=NULL;
if (bmp) delete bmp; bmp=NULL;
}
//---------------------------------------------------------------------------
isometric* isometric::operator = (const isometric &a)
{
resize(a.xs,a.ys);
bmp->Canvas->Draw(0,0,a.bmp);
int x,y,z;
for (z=0;z<gzs;z++)
for (y=0;y<gys;y++)
for (x=0;x<gxs;x++)
map[z][y][x]=a.map[z][y][x];
mx=a.mx; mx0=a.mx0; sel_x=a.sel_x;
my=a.my; my0=a.my0; sel_y=a.sel_y;
sh=a.sh; sh0=a.sh0; sel_z=a.sel_z;
pan_x=a.pan_x;
pan_y=a.pan_y;
return this;
}
//---------------------------------------------------------------------------
void isometric::resize(int _xs,int _ys)
{
if (_xs<1) _xs=1;
if (_ys<1) _ys=1;
if ((xs==_xs)&&(ys==_ys)) return;
bmp->SetSize(_xs,_ys);
xs=bmp->Width;
ys=bmp->Height;
if (pyx) delete pyx;
pyx=new DWORD*[ys];
for (int y=0;y<ys;y++) pyx[y]=(DWORD*) bmp->ScanLine[y];
// center view
cell2scr(pan_x,pan_y,gxs>>1,gys>>1,0);
pan_x=(xs>>1)-pan_x;
pan_y=(ys>>1)-pan_y;
}
//---------------------------------------------------------------------------
void isometric::mouse(int x,int y,TShiftState shift)
{
mx0=mx; mx=x;
my0=my; my=y;
sh0=sh; sh=shift;
scr2cell(sel_x,sel_y,sel_z,mx,my);
if ((sel_x<0)||(sel_y<0)||(sel_z<0)||(sel_x>=gxs)||(sel_y>=gys)||(sel_z>=gzs)) { sel_x=-1; sel_y=-1; sel_z=-1; }
}
//---------------------------------------------------------------------------
void isometric::draw()
{
int x,y,z,xx,yy;
// clear space
bmp->Canvas->Brush->Color=col_back;
bmp->Canvas->FillRect(TRect(0,0,xs,ys));
// grid
DWORD c0=col_zside;
col_zside=col_back;
for (y=0;y<gys;y++)
for (x=0;x<gxs;x++)
{
cell2scr(xx,yy,x,y,0);
cell_draw(xx,yy,_cell_type_ground,false);
}
col_zside=c0;
// cells
for (z=0;z<gzs;z++)
for (y=0;y<gys;y++)
for (x=0;x<gxs;x++)
{
cell2scr(xx,yy,x,y,z);
cell_draw(xx,yy,map[z][y][x],(x==sel_x)&&(y==sel_y)&&(z==sel_z));
}
// mouse0 cross
bmp->Canvas->Pen->Color=clBlue;
bmp->Canvas->MoveTo(mx0-10,my0); bmp->Canvas->LineTo(mx0+10,my0);
bmp->Canvas->MoveTo(mx0,my0-10); bmp->Canvas->LineTo(mx0,my0+10);
// mouse cross
bmp->Canvas->Pen->Color=clGreen;
bmp->Canvas->MoveTo(mx-10,my); bmp->Canvas->LineTo(mx+10,my);
bmp->Canvas->MoveTo(mx,my-10); bmp->Canvas->LineTo(mx,my+10);
// grid origin cross
bmp->Canvas->Pen->Color=clRed;
bmp->Canvas->MoveTo(pan_x-10,pan_y); bmp->Canvas->LineTo(pan_x+10,pan_y);
bmp->Canvas->MoveTo(pan_x,pan_y-10); bmp->Canvas->LineTo(pan_x,pan_y+10);
bmp->Canvas->Font->Charset=OEM_CHARSET;
bmp->Canvas->Font->Name="System";
bmp->Canvas->Font->Pitch=fpFixed;
bmp->Canvas->Font->Color=clAqua;
bmp->Canvas->Brush->Style=bsClear;
bmp->Canvas->TextOutA(5, 5,AnsiString().sprintf("Mouse: %i x %i",mx,my));
bmp->Canvas->TextOutA(5,20,AnsiString().sprintf("Select: %i x %i x %i",sel_x,sel_y,sel_z));
bmp->Canvas->Brush->Style=bsSolid;
}
//---------------------------------------------------------------------------
void isometric::cell2scr(int &sx,int &sy,int cx,int cy,int cz)
{
#ifdef isometric_layout_1
sx=pan_x+((cxs*(cx-cy))/2);
sy=pan_y+((cys*(cx+cy))/2)-(czs*cz);
#endif
#ifdef isometric_layout_2
sx=pan_x+(cxs*cx)+((cy&1)*cxs2);
sy=pan_y+(cys*cy/2)-(czs*cz);
#endif
}
//---------------------------------------------------------------------------
void isometric::scr2cell(int &cx,int &cy,int &cz,int sx,int sy)
{
int x0=-1,y0=-1,z0=-1,a,b,i,xx,yy;
#ifdef isometric_layout_1
// rough cell ground estimation (no z value yet)
// translate to (0,0,0) top left corner of the grid
xx=sx-pan_x-cxs2;
yy=sy-pan_y+cys2;
// change aspect to square cells cxs x cxs
yy=(yy*cxs)/cys;
// use the dot product with axis vectors to compute grid cell coordinates
cx=(+xx+yy)/cxs;
cy=(-xx+yy)/cxs;
cz=0;
// scan closest neighbors
#define _scann \
if ((cx>=0)&&(cx<gxs)) \
if ((cy>=0)&&(cy<gys)) \
{ \
for (cz=0;(map[cz+1][cy][cx]!=_cell_type_empty)&&(cz<czs-1);cz++); \
cell2scr(xx,yy,cx,cy,cz); \
if (map[cz][cy][cx]==_cell_type_full) yy-=czs; \
xx=(sx-xx); yy=((sy-yy)*cxs)/cys; \
a=(xx+yy); b=(xx-yy); \
if ((a>=0)&&(a<=cxs)&&(b>=0)&&(b<=cxs)) \
if (cz>=z0) { x0=cx; y0=cy; z0=cz; } \
}
_scann; // scan actual cell
for (i=gzs*czs;i>=0;i-=cys) // scan as many lines bellow actual cell as needed
{
cy++; _scann;
cx++; cy--; _scann;
cy++; _scann;
}
cx=x0; cy=y0; cz=z0; // return remembered cell coordinate
#undef _scann
#endif
#ifdef isometric_layout_2
// rough cell ground estimation (no z value yet)
cy=(2*(sy-pan_y))/cys;
cx= (sx-pan_x-((cy&1)*cxs2))/cxs;
cz=0;
// isometric tile shape crossing correction
cell2scr(xx,yy,cx,cy,cz);
xx=sx-xx;
yy=sy-yy;
if (xx<=cxs2) { if (yy> xx *cys/cxs) { cy++; if (int(cy&1)!=0) cx--; } }
else { if (yy>(cxs-xx)*cys/cxs) { cy++; if (int(cy&1)==0) cx++; } }
// scan closest neighbors
#define _scann \
if ((cx>=0)&&(cx<gxs)) \
if ((cy>=0)&&(cy<gys)) \
{ \
for (cz=0;(map[cz+1][cy][cx]!=_cell_type_empty)&&(cz<czs-1);cz++); \
cell2scr(xx,yy,cx,cy,cz); \
if (map[cz][cy][cx]==_cell_type_full) yy-=czs; \
xx=(sx-xx); yy=((sy-yy)*cxs)/cys; \
a=(xx+yy); b=(xx-yy); \
if ((a>=0)&&(a<=cxs)&&(b>=0)&&(b<=cxs)) \
if (cz>=z0) { x0=cx; y0=cy; z0=cz; } \
}
_scann; // scan actual cell
for (i=gzs*czs;i>=0;i-=cys) // scan as many lines bellow actual cell as needed
{
cy++; if (int(cy&1)!=0) cx--; _scann;
cx++; _scann;
cy++; if (int(cy&1)!=0) cx--; _scann;
}
cx=x0; cy=y0; cz=z0; // return remembered cell coordinate
#undef _scann
#endif
}
//---------------------------------------------------------------------------
void isometric::cell_draw(int x,int y,int tp,bool _sel)
{
TPoint pnt[5];
bmp->Canvas->Pen->Color=col_grid;
if (tp==_cell_type_empty)
{
if (!_sel) return;
bmp->Canvas->Pen->Color=col_sel;
pnt[0].x=x; pnt[0].y=y ;
pnt[1].x=x+cxs2; pnt[1].y=y+cys2;
pnt[2].x=x+cxs; pnt[2].y=y ;
pnt[3].x=x+cxs2; pnt[3].y=y-cys2;
pnt[4].x=x; pnt[4].y=y ;
bmp->Canvas->Polyline(pnt,4);
}
else if (tp==_cell_type_ground)
{
if (_sel) bmp->Canvas->Brush->Color=col_sel;
else bmp->Canvas->Brush->Color=col_zside;
pnt[0].x=x; pnt[0].y=y ;
pnt[1].x=x+cxs2; pnt[1].y=y+cys2;
pnt[2].x=x+cxs; pnt[2].y=y ;
pnt[3].x=x+cxs2; pnt[3].y=y-cys2;
bmp->Canvas->Polygon(pnt,3);
}
else if (tp==_cell_type_full)
{
if (_sel) bmp->Canvas->Brush->Color=col_sel;
else bmp->Canvas->Brush->Color=col_xside;
pnt[0].x=x+cxs2; pnt[0].y=y+cys2;
pnt[1].x=x+cxs; pnt[1].y=y;
pnt[2].x=x+cxs; pnt[2].y=y -czs;
pnt[3].x=x+cxs2; pnt[3].y=y+cys2-czs;
bmp->Canvas->Polygon(pnt,3);
if (_sel) bmp->Canvas->Brush->Color=col_sel;
else bmp->Canvas->Brush->Color=col_yside;
pnt[0].x=x; pnt[0].y=y;
pnt[1].x=x+cxs2; pnt[1].y=y+cys2;
pnt[2].x=x+cxs2; pnt[2].y=y+cys2-czs;
pnt[3].x=x; pnt[3].y=y -czs;
bmp->Canvas->Polygon(pnt,3);
if (_sel) bmp->Canvas->Brush->Color=col_sel;
else bmp->Canvas->Brush->Color=col_zside;
pnt[0].x=x; pnt[0].y=y -czs;
pnt[1].x=x+cxs2; pnt[1].y=y+cys2-czs;
pnt[2].x=x+cxs; pnt[2].y=y -czs;
pnt[3].x=x+cxs2; pnt[3].y=y-cys2-czs;
bmp->Canvas->Polygon(pnt,3);
}
}
//---------------------------------------------------------------------------
void isometric::map_random()
{
int i,x,y,z,x0,y0,r,h;
// clear
for (z=0;z<gzs;z++)
for (y=0;y<gys;y++)
for (x=0;x<gxs;x++)
map[z][y][x]=_cell_type_empty;
// add pseudo-random bumps
Randomize();
for (i=0;i<10;i++)
{
x0=Random(gxs);
y0=Random(gys);
r=Random((gxs+gys)>>3)+1;
h=Random(gzs);
for (z=0;(z<gzs)&&(r);z++,r--)
for (y=y0-r;y<y0+r;y++)
if ((y>=0)&&(y<gys))
for (x=x0-r;x<x0+r;x++)
if ((x>=0)&&(x<gxs))
map[z][y][x]=_cell_type_full;
}
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
布局仅定义坐标系轴方向(供您使用 #define isometric_layout_2 )。这使用 Borlands VCL Graphics::TBitmap所以如果你不使用 Borland 将其更改为任何 GDI 位图或将 gfx 部分覆盖到您的 gfx API (它仅与 draw() 和 resize() 相关)。还有 TShiftState是 的一部分VCL 它只是鼠标按钮和特殊键(如 shift、alt、ctrl)的状态,因此您可以使用 bool或其他任何东西(目前未使用,因为我还没有任何点击功能)。//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "win_main.h"
#include "isometric.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMain *Main;
isometric iso;
//---------------------------------------------------------------------------
void TMain::draw()
{
iso.draw();
Canvas->Draw(0,0,iso.bmp);
}
//---------------------------------------------------------------------------
__fastcall TMain::TMain(TComponent* Owner) : TForm(Owner)
{
Cursor=crNone;
iso.map_random();
}
//---------------------------------------------------------------------------
void __fastcall TMain::FormResize(TObject *Sender)
{
iso.resize(ClientWidth,ClientHeight);
draw();
}
//---------------------------------------------------------------------------
void __fastcall TMain::FormPaint(TObject *Sender)
{
draw();
}
//---------------------------------------------------------------------------
void __fastcall TMain::tim_redrawTimer(TObject *Sender)
{
draw();
}
//---------------------------------------------------------------------------
void __fastcall TMain::FormMouseMove(TObject *Sender, TShiftState Shift, int X,int Y) { iso.mouse(X,Y,Shift); draw(); }
void __fastcall TMain::FormMouseDown(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y) { iso.mouse(X,Y,Shift); draw(); }
void __fastcall TMain::FormMouseUp(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y) { iso.mouse(X,Y,Shift); draw(); }
//---------------------------------------------------------------------------
void __fastcall TMain::FormDblClick(TObject *Sender)
{
iso.map_random();
}
//---------------------------------------------------------------------------
[Edit1] 图形方法 O(1) 中提供了像素完美的 Sprite /单元格选择只需几行代码。idx[ys][xs] (x,y,z)单个像素内渲染单元的值(以 map 网格单元为单位)。我使用 32 位像素格式,所以我选择 12 x,y 的位和 8 z 的位 DWORD color = (x) | (y<<12) | (z<<24)
0xFFFFFFFF为空颜色,因此不会与单元格冲突 (0,0,0) .pyx[y][x]=color您还将像素渲染到阴影屏幕缓冲区 idx[y][x]=c哪里c是以 map 网格单元编码的单元格位置(参见 #1 )。mx,my所以如果它在范围内,只需读取阴影缓冲区并获取选定的单元格位置。 c=idx[my][mx]
if (c!=0xFFFFFFFF)
{
x= c &0x00000FFF;
y=(c>>12)&0x00000FFF;
z=(c>>24)&0x000000FF;
}
else
{
// here use the grid floor cell position formula from above approach if needed
// or have empty cell rendered for z=0 with some special sprite to avoid this case.
}
通过以上编码此 map (屏幕):

Title: Isometric 64x64 Outside Tileset
Author: Yar
URL: http://opengameart.org/content/isometric-64x64-outside-tileset
License(s): * CC-BY 3.0 http://creativecommons.org/licenses/by/3.0/legalcode
这里是 Win32 演示:关于javascript - 提高交错列等距网格上点击检测的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35885029/
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0
我正在寻找一个用ruby演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent
如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:
我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题
我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe
我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan
我编写了一个Ruby应用程序,它可以解析来自不同格式html、xml和csv文件的源中的大量数据。我如何找出代码的哪些区域花费的时间最长?有没有关于如何提高Ruby应用程序性能的好资源?或者您是否有任何始终遵循的性能编码标准?例如,你总是用加入你的字符串吗?output=String.newoutput或者你会使用output="#{part_one}#{part_two}\n" 最佳答案 好吧,有一些众所周知的做法,例如字符串连接比“#{value}”慢得多,但是为了找出您的脚本在哪里消耗了大部分时间或比所需时间更多,您需要进行分