this not question deep copying or cloning objects, there's millions of already, despite fact that's i've been looking myself @ first , fall on if option. seems unnecessarily overcomplicated simple thing this.
i've been translating c++ code delphi, blatantly copying tetris using sdl according this. it's been learning experience, in regard of sdl, in delphi kind of way. i'm linking particular page has code cannot translate. game works intended, there comes point have switch block falling , add squares others @ bottom, , set next block falling one.
here's of code without copying much: tsinglesquare
, tblock
, changefocusblock
procedure.
tsinglesquare = class private s_texturesurf: psdl_surface; s_blocktype: tblocktype; s_centerx, s_centery: integer; public constructor create(cx, cy: integer; t: psdl_surface; bt: tblocktype); destructor destroy; override; procedure draw(w: psdl_surface); procedure move(d: tdirection); function getcenterx: integer; function getcentery: integer; procedure setcenterx(lx: integer); procedure setcentery(ly: integer); end; ttmp_ar = array of integer; tsquaresarray = array of tsinglesquare; tblock = class private b_centerx, b_centery: integer; b_blocktype: tblocktype; b_squaresarray: tsquaresarray; b_texturesurf: psdl_surface; public constructor create(cx, cy: integer; ts: psdl_surface; bt: tblocktype); destructor destroy; override; procedure setupsquares(sx, sy: integer); procedure draw(w: psdl_surface); procedure move(d: tdirection); procedure rotate; function getrotatedsquares: ttmp_ar; function getsquaresarray: tsquaresarray; function getblocktype: tblocktype; end; procedure changefocusblock; var square_ar: tsquaresarray; i: integer; begin square_ar := g_focusblock.getsquaresarray setlength(g_oldsquares, (length(g_oldsquares) + length(square_ar))); := low(square_ar) high(square_ar) begin g_oldsquares[i+length(g_oldsquares)-length(square_ar)] := square_ar[i]; square_ar[i] := nil; end; g_focusblock := nil; g_focusblock := g_nextblock; g_nextblock := nil; g_focusblock.setupsquares(block_start_x, block_start_y); g_nextblock := tblock.create(next_block_circle_x, next_block_circle_y, gamebitmap, tblocktype(random(11))); end;
i know i'm not freeing g_focusblock
, i'm leaking memory, can't find appropriate place free in first place , if leave this, leaking memory issue. once started looking solution, bit me in ass later when try iterate on g_oldsquares
, understand why, squares still pointing g_focusblock
squares supposed freed. confusion comes in when add breakpoints @ every step , observe happening values, seems in order g_oldsquares
after g_focusblock
freed, after set g_nextblock
, create new next block. later iterating on g_oldsquares
notice part of squares getting overwritten, in memory getting reused? cant trust watchlist values true?
bottom line of wall of text understand happening g_oldsquares
, why it's values not change thought addresses same when inspecting via watchlist.
but more importantly proper course of action make work properly? aware of using tpersistent
, overriding it's assign
able assign objects between each other (although i'm not sure how accomplish either), right here still have rid of "link" or shared memory (i apologize incorrectly used words, i'm not fluent in programming) between g_oldsquares
, g_focusblock
able free latter.
let shaming begin.
edit:
accessviolation occurs when this
for := low(g_oldsquares) high(g_oldsquares) begin row := (g_oldsquares[i].getcentery - top) div row_size; inc(squares_in_row[row]) end; constructor tblock.create(cx, cy: integer; ts: psdl_surface; bt: tblocktype); var i: integer; begin b_centerx := cx; b_centery := cy; b_blocktype := bt; b_texturesurf:= ts; case bt of square_block..reverse_s_block: setlength(b_squaresarray, 4); straight_tri_block..bent_tri_block: setlength(b_squaresarray, 3); two_block: setlength(b_squaresarray, 2); dot_block: setlength(b_squaresarray, 1); end; setupsquares(cx, cy); end; destructor tblock.destroy; var i: integer; begin := low(b_squaresarray) high(b_squaresarray) b_squaresarray[i].free; inherited; end;
quoting sources http://aaroncox.net/tutorials/arcade/fallingblocks6.html
delete g_focusblock; // delete current focus block g_focusblock = g_nextblock; // set focus block next block g_focusblock->setupsquares(...); // set next block new block of random type g_nextblock = new cblock(...);
well, translate goes.
g_focusblock.free; // delete current focus block g_focusblock := g_nextblock; // set focus block next block g_focusblock.setupsquares( ... ); // set next block new block of random type g_nextblock := tblock.create(...);
is there anythign g_focusblock = null;
in c++ sources? no. invented g_focusblock := nil;
in delphi source jst not relate actual program , fantasy.
it coul make sense if create code based on refcounting memopry model , tinterfacedobject
you're translating plain-old-objects code manual memory management, c++ code does.
suggestion: make g_oldsquares
of tlist<tsinglesquare>
type or maybe tqueue<tsinglesquare>
.
then
g_oldsquares.addrange(square_ar);
or @ least
for square in square_ar g_oldsquares.add(square);
to move items array. more safe gymnastics index variables , array boundaries, can stumble upon typical "off one" error.
ps: tobjectlist<t>
option ownsobjects := true
might easier code against.
now, now...
destructor tblock.destroy; var i: integer; begin := low(b_squaresarray) high(b_squaresarray) b_squaresarray[i].free; inherited; end;
show me code here: http://aaroncox.net/tutorials/arcade/fallingblocks2.html can you?
let doing now!
- you created squares , put pointers them
tblock.bsquares_array
- inside
procedure changefocusblock
move pointerssquare
objects new container -g_oldsquares
- then try destroy squares int
tblock.destroy
despite objects still have pointersg_oldsquares
.
that redundant @ best , dangerous @ worst. have demand show g_focusblock.getsquaresarray
implementation - happen there ? , demand debug tblock.destroy
, check if array mistake still contains non-nil value.
accessviolation occurs when this
(*1*) := low(g_oldsquares) high(g_oldsquares) begin (*2*) row := (g_oldsquares[i].getcentery - top) div row_size; (*3*) inc(squares_in_row[row]) end;
here 3 lines of code. line result av ? specifics of of av, reading or writing , @ location ?
moving out of chat record
delete g_oldsquares[index]; g_oldsquares.erase(g_oldsquares.begin() + index); index--;
i guess you'd better rewrite while-loop (and modifying variable) instead of introducing bug-prone delayed nil squashing.
actually there neat trick - thing loop direction, when can delete element - safely avoiding enumeratinf element twice or skip element
for := tlist.count-1 downto 0 if somecondition tlist.delete[i];
using can take
for j := low(g_oldsquares) high(g_oldsquares) if (g_oldsquares[j] <> nil) if ((g_oldsquares[j].getcentery - top) div row_size) = begin g_oldsquares[j].free; g_oldsquares[j] := nil; end;
and refactor
for j := high(g_oldsquares) downto low(g_oldsquares) if g_oldsquares[j].row = g_oldsquares.delete(j);
assuming g_oldsquares
converted tobjectlist<tsquare>
type ownsobjects
property set true
.
Comments
Post a Comment