How to attach new member to instance of sprite in python?

For questions about using Classic.

Post » Mon Jun 06, 2011 6:16 am

Here is the test cap file:
http://dl.dropbox.com/u/5779181/objspv_access.zip

There are many instances of objA. I try to attach a new member named "_value" on each instance.
[code:vvgcwmd3]for _obj in objA:
_obj._value = 10
_obj = objA[0]
output.SetText("%d"%(_obj._value))[/code:vvgcwmd3]
And get the error message:
[quote:vvgcwmd3]TypeError: %d format: a number is required, not NoneType[/quote:vvgcwmd3]
from the last one "output.SetText("%d"%(_obj._value))".
It seems I can not attach new member to each instance.

Another way,
[code:vvgcwmd3]objA._value = 10
output.SetText("%d"%(objA._value))[/code:vvgcwmd3]
It works. I can attach new member to objA (not objA[0]).

What's different between "objA._value" and "objA[0]._value" in this case?
B
97
S
22
G
176
Posts: 4,108
Reputation: 103,019

Post » Tue Jun 07, 2011 12:23 am

[quote:2py1z69r]What's different between "objA._value" and "objA[0]._value" in this case?
[/quote:2py1z69r]
objA is the class to access objA instances and exists for the duration of the application. objA[0] creates a temporary class to access that instance.


Here is a fix:

Add this code to 'Start of Layout' before you run any other code to be able to attach new members to instances.
[code:2py1z69r]class _instance_values:
pass

_Instances._vals_=dict()
for _ot in _Instances.__dict__.items():
if _ot[0][0]=='_':
continue
_ot[1]._oldgetattr=_ot[1].__getattr__
def mygetattr(this, attr):
objkey=this.__dict__['__instance__']
if _Instances._vals_.has_key(objkey):
if hasattr(_Instances._vals_[objkey],attr):
return getattr(_Instances._vals_[objkey],attr)
return this._oldgetattr(attr)
_ot[1].__getattr__=mygetattr

_ot[1]._oldsetattr=_ot[1].__setattr__
def mysetattr(this, attr, value):
objkey=this.__dict__['__instance__']
if not _Instances._vals_.has_key(objkey):
_Instances._vals_[objkey]=_instance_values()
if not hasattr(this.__class__, attr) and attr not in this.__class__._otherAttrib:
return setattr(_Instances._vals_[objkey], attr, value)
return this._oldsetattr(attr,value)
_ot[1].__setattr__=mysetattr[/code:2py1z69r]
B
79
S
24
G
52
Posts: 4,725
Reputation: 39,713

Post » Tue Jun 07, 2011 10:31 am

Hi, Master of Python,

This code works in my case. Thanks.

New member is stored into global (hash)table _Instances._vals_
If an instance has been destroyed, the member of this dead instance in _Instances._vals_ will not be released automatic.

Btw, the variable type in construct only support "Number" and "String", so that I can not store instance directly.
I save the UID of instance and find it from adding an "compared" event, if I only use built-in event sheet (w/o python support).
Question:
Is there a faster way to keep the selected instances (w/o python support)?

With python, I save the {UID:instance} in a (hash)table, and clean the {UID:instance} pair if the instance has been destroyed.
Humm... Maybe I can cover the 'Destroy' method in objAInstance in _Instances to hang my clean method.

Question:
1. What is _Instances?
2. Will objA[0].Destroy() call objAInstance.Destroy()? Is objAInstance the class of objA[0]?

Thank you for your help :lol:
B
97
S
22
G
176
Posts: 4,108
Reputation: 103,019

Post » Fri Jun 10, 2011 3:24 pm

I test the "objA[0].Destroy() call objAInstance.Destroy()" is success. :lol: Now I can override Destroy method for doing some clean-up processes.
B
97
S
22
G
176
Posts: 4,108
Reputation: 103,019

Post » Fri Jun 10, 2011 4:03 pm

[quote:14olccbt]1. What is _Instances?[/quote:14olccbt]
It's basically just to hide\organize instance classes from the main global dict. It should never need to be accessed directly. Basically every object type causes 2 classes to be generated ex. Sprite and SpriteInstance. SpriteInstance is a class that points to a particular instance of sprite.

[quote:14olccbt]2. Will objA[0].Destroy() call objAInstance.Destroy()? Is objAInstance the class of objA[0]?
[/quote:14olccbt]Yes for the first. For the second objA[0] is a objAInstance.

The only issue is if you destroy the object with events, the python destroy() is not called and the custom methods will not be cleaned up.
B
79
S
24
G
52
Posts: 4,725
Reputation: 39,713

Post » Fri Jun 10, 2011 4:48 pm

Thanks, it's very clear.

Sorry for another question, I try to override System.Create() for the same reason, to add some custom initialize. How to get the class of "System"?
B
97
S
22
G
176
Posts: 4,108
Reputation: 103,019

Post » Fri Jun 10, 2011 9:57 pm

System is a bit different since there is only one instance of System.

get the system class with this:
[code:29imus8b]System.__class__[/code:29imus8b]
B
79
S
24
G
52
Posts: 4,725
Reputation: 39,713

Post » Sat Jun 11, 2011 12:39 am

It works. Thank you again.
B
97
S
22
G
176
Posts: 4,108
Reputation: 103,019


Return to Help & Support using Construct Classic

Who is online

Users browsing this forum: No registered users and 3 guests