翎风是否考虑增加客户端平滑移动模式
本帖最后由 hahaq 于 2023-11-11 22:24 编辑加入 类似传奇世界的平滑模式 ,走起来四周物体不再晃眼。
procedure TPlayScene.DrawMap(layer: TMapLayer);
var
x, y, xoff, yoff: Integer;
surface: TTexture;
begin
for y := m_clientRect.Top to m_clientRect.Bottom + MAP_GRID_HEIGHT * 2 do begin
for x := m_clientRect.Left - 4 to m_clientRect.Right + 4 do begin
surface := Map.GetTextureAtLayer(x, y, layer, xoff, yoff);
if surface <> nil then begin
surface.Draw((x - m_clientRect.Left) * UNITX + xoff - g_MySelf.m_nShiftX,
(y - m_clientRect.Top) * UNITY + yoff - g_MySelf.m_nShiftY);
end;
end;
end;
end;
procedure TPlayScene.DrawObjLayer;
var
x, y, i, j, px, py, xoff, yoff: Integer;
actor: TActor;
surface: TTexture;
ev: TEvent;
meff: TMagicEff;
list: TList;
dropItem: pTDropItem;
showItem: PTShowItem;
name: string;
rect: TRect;
width, height: Integer;
begin
for y := m_clientRect.Top to m_clientRect.Bottom + MAP_GRID_HEIGHT * 2 do begin
{ 渲染建筑 }
for x := m_clientRect.Left - 4 to m_clientRect.Right + 4 do begin
surface := Map.GetTextureAtLayer(x, y, ML_OBJ, xoff, yoff);
if surface <> nil then begin
surface.Draw((x - m_clientRect.Left) * UNITX + xoff - g_MySelf.m_nShiftX,
(y - m_clientRect.Top) * UNITY + yoff - g_MySelf.m_nShiftY);
end;
end;
{ 渲染事件 }
g_eventRenderMgr.Render(y);
// for i := 0 to EventMan.EventList.Count - 1 do begin
// ev := TEvent(EventMan.EventList);
// if ev.m_nY = y then begin
// ev.DrawEvent(m_ObjSurface,
// (ev.m_nX - m_clientRect.Left) * UNITX,
// (ev.m_nY - m_clientRect.Top) * UNITX
// );
// end;
// end;
{ 渲染掉落物品 }
if g_boDrawDropItem then begin
g_DropedItemList.Lock;
try
for i := 0 to g_DropedItemList.Count - 1 do begin
list := TList(g_DropedItemList);
if list.Count <= 0 then Break;
dropItem := pTDropItem(list);
if (dropItem = nil) or (y <> (dropItem.Y)) then Continue;
ifdropItem.Looks in then
surface := g_dropitems.Images['掉落_' + RES_BOOKS]
else
if dropItem.Name = g_sGoldName then
surface := g_dropitems.Images['掉落_金币大.png']
else
surface := g_dropitems.Images['掉落_' + dropItem.Name + '.png'];
if surface = nil then Continue;
px := (dropItem.X - m_ClientRect.Left) * UNITX - surface.Width div 2 - g_MySelf.m_nShiftX - HALFX;
py := (dropItem.Y - m_ClientRect.Top) * UNITY - surface.Height div 2 - g_MySelf.m_nShiftY - HALFY;
surface.Draw(px, py);
{显示掉落物品名}
if g_boDropItemFlash then begin
width := TextWidth(dropItem.Name) + 4;
height := TextHeight(dropItem.Name) + 2;
rect.Left := px + (surface.Width - width) div 2;
rect.Top := py - height - 4;
rect.Right := rect.Left + width;
rect.Bottom := rect.Top + height;
surface.FillRectAlpha(rect, $00004C4C, 125);
ImageDraw.TextOut(rect.Left + 2, rect.Top + 1, dropItem.Name);
end;
end
finally
g_DropedItemList.UnLock;
end;
end;
{ 渲染生物 }
for i := 0 to m_actorList.Count - 1 do begin
actor := TActor(m_ActorList.Items);
if (actor.m_nRy = y) then begin
if actor = g_AttackLockActor{g_MagicLockActor} then
begin
if not g_AttackLockActor.m_boDeath then begin
DrawSelEffect(actor);
end else begin
g_AttackLockActor := nil;
end;
end;
if (not g_boDrawMonsterDead) and actor.m_boDeath then Continue;
actor.Render(
(actor.m_nRx - m_ClientRect.Left) * UNITX + actor.m_nShiftX - g_MySelf.m_nShiftX,
(actor.m_nRy - m_ClientRect.Top) * UNITY + actor.m_nShiftY - g_MySelf.m_nShiftY
);
end;
end;
{ 绘制生物特效 }
for i := 0 to m_ActorList.Count - 1 do begin
Actor := m_ActorList;
Actor.DrawEff(m_ObjSurface,
(Actor.m_nRx - m_ClientRect.Left) * UNITX,
(Actor.m_nRy - m_ClientRect.Top - 1) * UNITY);
end;
end;
{ 绘制武功特效 }
for i := 0 to m_EffectList.Count - 1 do begin
meff := TMagicEff(m_EffectList);
meff.DrawEff(m_ObjSurface);
end;
{ 渲染飞行特效 }
for i := 0 to m_FlyList.Count - 1 do begin
meff := TMagicEff(m_FlyList.Items);
if j = (meff.ry - Map.BlockTop) then begin
meff.DrawEff(m_ObjSurface);
end;
end;
// if g_NewStatus = sConfusion then begin
// msgstr := Format('You are confused, will return to normal in %d seconds. ', );
// with m_ObjSurface do begin
// FontSize := MainForm.Canvas.Font.Size;
// MainForm.Canvas.Font.Size := 18;
// m_ObjSurface.BoldTextOut((SCREENWIDTH - m_ObjSurface.TextWidth(msgstr)) div 2, (SCREENHEIGHT - 600) + 200, msgstr,
// clRed, clWhite);
// MainForm.Canvas.Font.Size := FontSize;
// end;
// end;
end;
function TPlayScene.calcShowActorNameY(actor: TActor; var iShowY: Integer) : Integer;
begin
//计算Y坐标 用于显示 人物名
if g_boShowNameOnHead then begin
Result := iShowY;
end else begin
Result := actor.m_nSayY + actor.SayOff div 2;
end;
end;
procedure TPlayScene.DrawActorInfo;
var
i: Integer;
actor: TActor;
name: string;
color: TColor;
iShowNameY, iTmp: Integer;
iShowNameX: Integer;
begin
for i := 0 to m_ActorList.Count - 1 do begin
actor := TActor(m_ActorList);
iShowNameY := actor.m_nSayY;
if not actor.m_boDeath then begin
if g_NewStatus = sBlind then Continue;
{ 绘制血条 }
if not (actor.m_btRace in ) then
actor.RenderHealth(iShowNameY);
{NPC 只显示名字}
if (actor.m_btRace in ) then begin
if g_boExtrudeNPC then
color := clLime
else color := actor.m_nNameColor;
actor.NameTextOut(actor.m_sUserName, actor.m_nSayX, calcShowActorNameY(actor, iShowNameY), color);
if (actor.m_btRace <> RC_ARROWGUARD) then Continue; //跳过,下一角色
end;
if{怪物} (actor.m_btRace <> 0) and (actor.m_btRace <> 1) then begin
if g_boDrawMonsterName then begin
if g_boExtrudeMonsterName then begin
if actor.m_btRace in {道士宠物} then
color := clLime
else color := clRed;
end else color := actor.m_nNameColor;
actor.NameTextOut(actor.m_sUserName, actor.m_nSayX, calcShowActorNameY(actor, iShowNameY), color);
end;
end
else {玩家} if (actor.m_btRace = RCC_USERHUMAN{男}) or (actor.m_btRace = 1{女}) then begin
if (Actor = g_MySelf) and g_boExtrudeSelf then
color := clLime
else color := actor.m_nNameColor;
{角色名}
iTmp := 0;
name := ''; {鼠标指向角色 - 显示名称}
if g_boDrawName or ((actor <> g_MySelf) and (actor = g_FocusCret)){其他玩家} or
((actor = g_MySelf) and IsSelectMyself(g_nMouseX, g_nMouseY)) {自己} then begin
name := actor.m_sUserName;
end;
if name <> '' then begin
//iTmp为人名显示Y坐标 - 16 iShowNameY - 为头顶坐标
iTmp := actor.NameTextOut(name, actor.m_nSayX, calcShowActorNameY(actor, iShowNameY), color);
if g_boShowNameOnHead then iShowNameY := iTmp;
end;
{行会名}
if g_boShowNameOnHead then begin
if (iTmp = 0) then iTmp := iShowNameY;
if not g_boShowGuildNickNameOnHead then iTmp := actor.m_nSayY + actor.SayOff div 2;
end else begin
if g_boShowGuildNickNameOnHead then iTmp := iShowNameY
else if iTmp = 0 then iTmp := actor.m_nSayY + actor.SayOff div 2;
end;
name := '';
if (g_boDrawGuildName) and (actor.m_sDescGuildName <> '') then begin
if actor.m_sDescRankName = '' then
name := actor.m_sDescGuildName + '\' + name
else
name := actor.m_sDescGuildName + '[' + actor.m_sDescRankName + ']' + '\' + name;
end;
if name <> '' then begin
iTmp := actor.NameTextOut(name, actor.m_nSayX, iTmp, color);
if g_boShowGuildNickNameOnHead then iShowNameY := iTmp;
end;
{摆摊:商铺名}
if actor.m_boStartStore then begin
iShowNameX :=actor.m_nSayX - (TextWidth(actor.m_sMyStoreName) + g_UIStoreName.Width + 2) div 2;
g_UIStoreName.Draw(iShowNameX, iShowNameY - 5);
ImageDraw.TextOut(iShowNameX + g_UIStoreName.Width + 2, iShowNameY, actor.m_sMyStoreName, clLime, ColorContour);
Dec(iShowNameY, 23);
end;
end;
{ 绘制生命改变 攻击/毒等扣血值}
if g_boDrawHurtNum and (g_NewStatus <> sBlind) then begin
Actor.ShowHealthStatus;
end;
end;
{ 显示角色说话文字 }
if g_NewStatus <> sBlind then begin
Actor.ShowSayMsg(m_ObjSurface, iShowNameY);
end;
end;
if (g_nAreaStateValue and $04) <> 0 then begin
m_ObjSurface.BoldTextOut(SCREENWIDTH div 2 - 60, 0, '[攻城区]');
end;
if (g_nAreaStateValue and $05) <> 0 then begin
m_ObjSurface.BoldTextOut(SCREENWIDTH div 2 - 20, 0, '[决斗区]');
end;
if (g_nAreaStateValue and $06) <> 0 then begin
m_ObjSurface.BoldTextOut(SCREENWIDTH div 2 - 50, 0, '[安全区]');
end;
end;
procedure TPlayScene.ClearDropItem;
var
I, II: Integer;
List: TList;
DropItem: pTDropItem;
begin
{
if not CanDraw then Exit;
}
g_DropedItemList.Lock;
try
for I := g_DropedItemList.Count - 1 downto 0 do begin
List := TList(g_DropedItemList.Items);
if List.Count > 0 then begin
DropItem := List.Items;
if (abs(DropItem.X - g_MySelf.m_nCurrX) > 30) and (abs(DropItem.Y - g_MySelf.m_nCurrY) > 30) then begin
for II := 0 to List.Count - 1 do begin
DropItem := List.Items;
Dispose(DropItem);
end;
List.Free;
g_DropedItemList.Delete(I);
end;
end;
end;
finally
g_DropedItemList.UnLock;
end;
end;
procedure TPlayScene.Run(RunSelf: Boolean);
var
I, k: Integer;
movetick: Boolean;
evn: TEvent;
Actor: TActor;
meff: TMagicEff;
effectRender: TEffectRender;
dwCheckTime, dwTestCheckTime: LongWord;
nIdx: Integer;
boCheckTimeLimit: Boolean;
dwStepMoveTime: LongWord;
dwTickTime: LongWord;
begin
if (g_MySelf = nil) then Exit;
g_boDoFastFadeOut := False;
{
m_nAniCount: 控制动画渲染 ? ? ?
}
if GetTickCount - m_dwAniTime >= 50 then begin
m_dwAniTime := GetTickCount;
Inc(m_nAniCount);
if m_nAniCount > 100000 then m_nAniCount := 0;
end;
{ Ryan - Some Serious Problem Here I Think, Needs Looking Into }
try
nIdx := 0;
dwCheckTime := g_sysTimeTick;
boCheckTimeLimit := False;
while True do begin
if nIdx >= m_ActorList.Count then Break;
Actor := TActor(m_ActorList.Items);
if (not RunSelf) and (Actor = g_MySelf) then begin
Inc(nIdx);
Continue;
end;
dwTestCheckTime := g_sysTimeTick;
movetick := Actor.CanMove;
if movetick then begin
Actor.m_boLockEndFrame := False;
end;
if not Actor.m_boLockEndFrame then begin
Actor.ProcMsg;
Actor.Run;
if movetick then begin
if Actor.Move(Actor.m_nMoveStepCount) then begin
Inc(nIdx);
Continue;
end;
end;
if Actor <> g_MySelf then
Actor.ProcHurryMsg;
end;
if Actor = g_MySelf then Actor.ProcHurryMsg;
if Actor.m_nWaitForRecogId <> 0 then begin
if Actor.IsIdle then begin
DelChangeFace(Actor.m_nWaitForRecogId);
NewActor(Actor.m_nWaitForRecogId, Actor.m_nCurrX, Actor.m_nCurrY, Actor.m_btDir, Actor.m_nWaitForFeature, Actor.m_nWaitForStatus);
Actor.m_nWaitForRecogId := 0;
Actor.m_boDelActor := True;
end;
end;
if Actor.m_boDelActor then begin
m_ActorList.Delete(nIdx);
UpDataFreeActorList(Actor);
if g_TargetCret = Actor then g_TargetCret := nil;
if g_FocusCret = Actor then g_FocusCret := nil;
if g_MagicTarget = Actor then g_MagicTarget := nil;
if g_MyHero = Actor then g_MyHero := nil;
if g_SerieTarget = Actor then g_SerieTarget := nil;
end
else begin
Inc(nIdx);
end;
end;
except
DebugOutStr('Error 1: PlayerSence.Run');
end;
try
{ 处理地面特效 }
nIdx := 0;
while True do begin
if nIdx >= m_GroundEffectList.Count then Break;
meff := m_GroundEffectList;
if meff.m_boActive then begin
if not meff.Run then begin
m_GroundEffectList.Delete(nIdx);
meff.Free;
Continue;
end;
end;
Inc(nIdx);
end;
{ 处理特武功效 }
nIdx := 0;
while True do begin
if nIdx >= m_effectRenderList.Count then Break;
effectRender := m_effectRenderList;
if not effectRender.Running then begin
effectRender.Free;
m_effectRenderList.Delete(nIdx);
end;
Inc(nIdx);
end;
{ 处理特武功效 }
nIdx := 0;
while True do begin
if nIdx >= m_EffectList.Count then Break;
meff := m_EffectList;
if meff.m_boActive then begin
if not meff.Run then begin
meff.Free;
m_EffectList.Delete(nIdx);
Continue;
end;
end;
Inc(nIdx);
end;
{ 处理飞行特效 }
nIdx := 0;
while True do begin
if nIdx >= m_FlyList.Count then Break;
meff := m_FlyList;
if meff.m_boActive then begin
if not meff.Run then begin
meff.Free;
m_FlyList.Delete(nIdx);
Continue;
end;
end;
Inc(nIdx);
end;
{ 执行事件逻辑 }
g_eventRenderMgr.Update;
EventMan.Execute;
except
DebugOutStr('Error 2: PlayerSence.Run');
end;
try
{ 清除超过显示范围的物品数据 }
ClearDropItem();
{ 清除超过显示范围的魔法数据 }
for k := 0 to EventMan.EventList.Count - 1 do begin
evn := TEvent(EventMan.EventList);
if (abs(evn.m_nX - g_MySelf.m_nCurrX) > 30) and (abs(evn.m_nY - g_MySelf.m_nCurrY) > 30) then begin
evn.Free;
EventMan.EventList.Delete(k);
Break;
end;
end;
{ 播放烟花声音 }
for k := 0 to EventMan.EventList.Count - 1 do begin
evn := TEvent(EventMan.EventList);
if (abs(evn.m_nX - g_MySelf.m_nCurrX) <= 15) and (abs(evn.m_nY - g_MySelf.m_nCurrY) <= 15) then begin
if evn.m_nEventType in then begin
if TFlowerEvent(evn).m_nExplosionSound > 0 then begin
PlaySound(TFlowerEvent(evn).m_nExplosionSound);
TFlowerEvent(evn).m_nExplosionSound := -2;
end;
end;
end;
end;
except
DebugOutStr('Error 3: PlayerSence.Run');
end;
g_dwRefreshMessagesTick := g_sysTimeTick;
end;
procedure TPlayScene.PlayScene(MSurface: TTexture);
var
msgstr: string;
nSnowX, nSnowY: Integer;
FontSize: Integer;
surface: TTexture;
mode: Integer;
rect: TRect;
width, height, i: Integer;
s,s1: Int64;
begin
{ 角色加载中 }
if (g_MySelf = nil) then begin
Exit;
end;
if Assigned(g_PlugInfo.HookPlayScene) then begin
if g_PlugInfo.HookPlayScene(MSurface) then Exit;
end;
Run(True);
{ 失明状态 }
if g_NewStatus = sBlind then begin
msgstr := Format('你已进入失明状态,持续%d秒...', );
with MSurface do begin
FontSize := MainForm.Canvas.Font.Size;
MainForm.Canvas.Font.Size := 18;
BoldTextOut((SCREENWIDTH - TextWidth(msgstr)) div 2, (SCREENHEIGHT - 600) + 200, msgstr);
MainForm.Canvas.Font.Size := FontSize;
end;
Exit;
end;
{ 画面震动 }
if g_boVibration then begin
g_nVibrationX := g_nVibrationX + g_VibrationValue.X;
g_nVibrationY := g_nVibrationY + g_VibrationValue.Y;
Inc(g_nVibrationPos);
if g_nVibrationPos >= Length(g_VibrationValue) then begin
g_nVibrationPos := 0;
Inc(g_nVibrationCount);
end;
g_boVibration := g_nVibrationCount < g_nVibrationTotal;
end;
{ 客户端窗口定位 }
with m_clientRect do begin
Top := g_MySelf.m_nRy - (SCREENHEIGHT div UNITY + 1) div 2;
Left := g_MySelf.m_nRx - (SCREENWIDTH div UNITX + 1) div 2;
Right := g_MySelf.m_nRx + (SCREENWIDTH div UNITX - 1) div 2;
Bottom := g_MySelf.m_nRy + (SCREENHEIGHT div UNITY - 1) div 2;
end;
m_nOldCurrX := m_nCurrX;
m_nOldCurrY := m_nCurrY;
m_nCurrX := g_MySelf.m_nShiftX;
m_nCurrY := g_MySelf.m_nShiftY;
if m_nCurrX < 0 then m_nCurrX := 0;
if m_nCurrY < 0 then m_nCurrY := 0;
nSnowX := m_nCurrX;
nSnowY := m_nCurrY;
{ 更新地图块 }
Map.UpdateMapBlock(g_MySelf.m_nRx, g_MySelf.m_nRy);
Map.UpdateSceneMgr;
{ 绘制地下表层 }
DrawMap(ML_GROUND);
{ 绘制地表层 }
DrawMap(ML_SURFACE);
{ 绘制上地表层 }
DrawMap(ML_TILE);
{ 绘制对象层 }
DrawObjLayer;
{ 绘制天空层 }
DrawMap(ML_SKY);
if (g_MySelf <> nil) and IsValidActor(g_MySelf) and (g_MySelf.m_nState and $00800000 = 0) then begin
g_MySelf.Render((g_MySelf.m_nRx - m_ClientRect.Left) * UNITX,
(g_MySelf.m_nRy - m_ClientRect.Top) * UNITY, True, 110);
end;
if (g_FocusCret <> nil) and IsValidActor(g_FocusCret) and (g_FocusCret <> g_MySelf) and
(g_FocusCret.m_nState and $00800000 = 0) then begin
g_FocusCret.Render(
(g_FocusCret.m_nRx - m_ClientRect.Left) * UNITX + g_FocusCret.m_nShiftX - g_MySelf.m_nShiftX,
(g_FocusCret.m_nRy - m_ClientRect.Top) * UNITY + g_FocusCret.m_nShiftY - g_MySelf.m_nShiftY,
True, 110
);
end;
if (g_MagicTarget <> nil) and IsValidActor(g_MagicTarget) and (g_MagicTarget <> g_MySelf) and
(g_MagicTarget.m_nState and $00800000 = 0) then begin
g_MagicTarget.Render(
(g_MagicTarget.m_nRx - m_ClientRect.Left) * UNITX + g_MagicTarget.m_nShiftX - g_MySelf.m_nShiftX,
(g_MagicTarget.m_nRy - m_ClientRect.Top) * UNITY + g_MagicTarget.m_nShiftY - g_MySelf.m_nShiftY,
True, 110
);
end;
{掉落物品名字}
if g_FocusItem <> nil then begin
if g_FocusItem.Looks in then
surface := g_dropitems.Images['掉落_' + RES_BOOKS]
else
if g_FocusItem.Name = g_sGoldName then
surface := g_dropitems.Images['掉落_金币大.png']
else
surface := g_dropitems.Images['掉落_' + g_FocusItem.Name + '.png'];
if surface <> nil then begin
nSnowX := (g_FocusItem.X - m_ClientRect.Left) * UNITX - surface.Width div 2 - g_MySelf.m_nShiftX - HALFX;
nSnowY := (g_FocusItem.Y - m_ClientRect.Top) * UNITY - surface.Height div 2 - g_MySelf.m_nShiftY - HALFY;
surface.Draw(nSnowX, nSnowY);
surface.DrawEff(nSnowX, nSnowY, ceBright, 170);
width := TextWidth(g_FocusItem.Name) + 4;
height := TextHeight(g_FocusItem.Name) + 2;
rect.Left := nSnowX + (surface.Width - width) div 2;
rect.Top := nSnowY - height - 4;
rect.Right := rect.Left + width;
rect.Bottom := rect.Top + height;
surface.FillRectAlpha(rect, $00004C4C, 125);
ImageDraw.TextOut(rect.Left + 2, rect.Top + 1, g_FocusItem.Name);
end;
end;
{ 绘制名字、血条等}
DrawActorInfo;
DrawTargetHP();
{ 绘制武功特效 }
for i := 0 to m_effectRenderList.Count - 1 do begin
TEffectRender(m_effectRenderList).Render;
end;
{ 地图掩盖层 }
if (Map.Name = 'jjc') or (Map.Name = 'mq0') or (Map.Name = 'mz0') or (Map.Name = 'shatu') then begin
surface := nil;
end
else begin
surface := g_resUi.Images['map_mask.png'];
end;
if surface <> nil then begin
surface.Draw(0, 0);
end;
DrawBloodBox();
if g_jjrelive then begin
s := Round((GetTickCount - g_jjreliveTick) div 1000);
if s <= 10 then begin
ImageDraw.TextOut(100, 100, IntToStr(s));
end else begin
frmMain.SendMerchantDlgSelect(g_nCurMerchant, '@revivejjc');
g_jjrelive := False;
end;
end;
if g_startplay then begin
s1 := Round((GetTickCount - g_starttime) div 1000);
if s1 < 5 then begin
g_timepic.Draw((SCREENWIDTH - g_timepic.Width) div 2, (SCREENHEIGHT - g_timepic.Height) div 2);
end else begin
if s1 = 5 then begin
g_timepic.Draw((SCREENWIDTH - g_timepic.Width) div 2, (SCREENHEIGHT - g_timepic.Height) div 2);
end else begin
g_startplay := False;
end;
end;
end;
end;
{-------------------------------------------------------}
private
FPoints: array of TPoint; {...} procedure TForm1.CalculateGraph;
var
xRangePixels, yRangePixels: Integer;
origin: TPoint;
radian, interval: Double;
i: Integer;
begin
xRangePixels := (paintbox1.Width - 2) div 4; { pixels in Pi }
yRangePixels := (paintbox1.Height - 2) div 2; { pixels in 1 }
origin := Point(paintbox1.Width div 2, paintbox1.Height div 2);
radian := -2.0 * Pi;
interval := 4.0 * Pi / 144.0;
for i := 0 to High(FPoints) do
begin
FPoints.X := origin.x + Round(radian * xRangePixels / Pi);
FPoints.Y := origin.y - Round(sin(radian) * yRangePixels);
radian := radian + interval;
end;
end; procedure TForm1.PaintBox1Paint(Sender: TObject);
var
origin: TPoint;
xRangePixels, yRangePixels: Integer;
begin
with PaintBox1.Canvas do
begin
{ Fill background in white }
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
Fillrect(paintbox1.BoundsRect); { Paint a coordinate cross }
origin := Point(paintbox1.Width div 2, paintbox1.Height div 2);
Pen.Color := clBlack;
Pen.Style := psSolid;
Pen.Width := 1;
MoveTo(1, origin.Y);
LineTo(paintbox1.Width - 1, origin.y);
MoveTo(origin.x, 1);
LineTo(origin.x, paintbox1.Height - 1); { Paint some ticks and label the axis }
Font.Name := 'Symbol';
Font.Size := 8;
Font.Color := clBlack;
xRangePixels := (paintbox1.Width - 2) div 4; { pixels in Pi }
yRangePixels := (paintbox1.Height - 2) div 2; { pixels in 1 } { X axis }
MoveTo(origin.x - 2 * xRangePixels, origin.y - 4);
LineTo(origin.x - 2 * xRangePixels, origin.y + 4);
TextOut(origin.x - 2 * xRangePixels + 2, origin.y + 2, '-2p');
MoveTo(origin.x - xRangePixels, origin.y - 4);
LineTo(origin.x - xRangePixels, origin.y + 4);
TextOut(origin.x - xRangePixels + 2, origin.y + 2, '-p');
MoveTo(origin.x + xRangePixels, origin.y - 4);
LineTo(origin.x + xRangePixels, origin.y + 4);
TextOut(origin.x + xRangePixels - 2 - TextWidth('p'), origin.y + 2, 'p');
MoveTo(origin.x + 2 * xRangePixels, origin.y - 4);
LineTo(origin.x + 2 * xRangePixels, origin.y + 4);
TextOut(origin.x + 2 * xRangePixels - 2 - TextWidth('2p'), origin.y + 2, '2p');
{ Y axis }
MoveTo(origin.x - 4, origin.y - yRangePixels);
LineTo(origin.x + 4, origin.y - yRangePixels);
TextOut(origin.x + 4, origin.y - yRangePixels, '1.0');
MoveTo(origin.x - 4, origin.y - yRangePixels div 2);
LineTo(origin.x + 4, origin.y - yRangePixels div 2);
TextOut(origin.x + 4, origin.y - (yRangePixels + TextHeight('1')) div 2, '0.5');
MoveTo(origin.x - 2, origin.y + yRangePixels div 2);
LineTo(origin.x + 2, origin.y + yRangePixels div 2);
TextOut(origin.x + 3, origin.y + (yRangePixels - TextHeight('1')) div 2, '-0.5');
MoveTo(origin.x - 2, origin.y + yRangePixels);
LineTo(origin.x + 2, origin.y + yRangePixels);
TextOut(origin.x + 3, origin.y + yRangePixels - TextHeight('1'), '-1.0'); {Paint the graph }
Pen.Color := clBlue;
Polyline(FPoints);
end;
end; procedure TForm1.FormResize(Sender: TObject);
begin
CalculateGraph;
end; procedure TForm1.FormCreate(Sender: TObject);
begin
CalculateGraph;
end; 以上是delphi 别人发的 平滑移动代码望翎风工作人员 关注一下。 666,虽然看不懂想让你讲中文,但还是给你点个赞 是的,传奇确实走起来感觉画面很难受,就像帧数太低了一样,眼睛看起累 对啊 虽然平滑移动 有的人 觉得无所谓 但是现在很多年轻人也喜欢玩玩但是 一玩晃眼 就放弃了 。。。
本身传奇的 玩法 和 pk是秒杀现在的网游的 。。只是画面没平滑倒是很多 90 00后 接纳不来哦。。
希望翎风老大们 考虑下。。。做个客户端开关 喜欢的开 不喜欢的不开平滑 即可!!!
应该可以实现。。。。 支持,要是能有平滑程度调解就更吊了,因为最平滑的效果,就是现在页游的效果,反而感觉不好.但原版太不平滑的效果,时间长了确实费眼睛. 对 平滑可以分三个档次参数玩家自己在客户端内挂或者登录器上设置即可!!! 本帖最后由 hahaq 于 2023-11-12 17:42 编辑
实现以后 绝对会大大提升游戏的体验。。
传奇20多年了 相比现在的游戏其他方面并不落后
唯独落后在绘图上 。。。
神作:暗黑2 有了重制版 弥补了这一块。
暗黑2 有个 dx插件 可以让暗黑2 玩起来 像 奇迹一样 有立体3d景深的感觉。。
传奇要是写这么个插件 那 画面了不得了。。。。。