Eisfläche

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Servus zusammen :-),

ich schreibe mir gerade eine Eisfläche auf der ich mit der Mouse (in meinem Fall Finger, weil es ein TouchScreen ist) schreiben kann. Dachte eigentlich, das das schnell gehen sollte.
stoße aber gerade an ein Problem.
Ich möchte transparent zeichnen und wenn ich gezeichnet habe, möchte ich das der
Bildschirm nach einer Zeit x wieder "zufriert". Schön wäre sogar eine Art fade effekt. Ich dachte dabei an ein array in dem ich mir
die Mouseposition merke, jedoch weiß ich nicht, wie ich das Bild nur an der Position wieder ersetze...

Hat jemand eine Idee?
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Kannst du nicht einfach alle x Millisekunden die komplette Fläche mit der Original-Textur und 0.01 Deckung wieder überzeichnen? Dann verschwindet die Zeichnung langsam.
Bottle: Micro Web Framework + Development Blog
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

hmmm, dann bräuchte ich aber einen Counter für jedes Pixel, weil die ja zu einem unterschiedlichen Zeitpunkt bemalt wurden.

Allerdings finde ich die Idee dennoch Klasse, statt Eis könnte man auch den Bildschirm
beschlagen lassen und dann einfach von einem "pusten" ausgehend, den Bildschirm beschlagen, dann hätte ich das Zeitproblem nicht.
Du weißt nicht zufällig, wie ich den Deckungsgrad angeben kann?

EDIT: Eventuell durch eine Angabe der Helligkeit?
Sodass man das Bild immer "dunkler" werden lässt... ist aber glaub ich eher die hässliche variante...
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Als Zwischenlösung hab ich

_image.set_alpha(i)
screen.blit(_image, (0, 10))

gewählt, falls es was besseres gibt nur her damit...
aber das ist derzeit meine Zwischenlösung, damit fadet das was übermal wurde immer wieder weg, sobald es gemalt wurde... man muss es halt vorher auf 255 setzen und
nach dem zeichnen des bildes auf 0 und die 0 dann stückweise erhöhen...
dann siehts so aus als würde es rausfaden... bzw beschlagen :-)
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Da das jetzt funktioniert, ich habs mir mal schöner gemacht ;-)
Eine neue Frage, ich möchte den beschlagenen Bildschirmwegwischen können,
(kann ich) aber ich will das der Hintergrund zum Vorschein kommt.
Von mir aus auch 2 übereinander gelegte Bilder, ne Art Overlay Funktion...
sprich transparent malen... jemand eine idee?
Ich hab leider das gefunden:
The alpha value will be written directly into the Surface if it contains pixel alphas, but the draw function will not draw transparently.

Zerstört das meinen Traum oder gibts n Workaround?
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

aloah...
ich hab leider noch keine antwort auf meine Frage gefunden, wie man transparent zeichnen kann. Wäre super falls das jmd liest oder sich jmd damit beschäftigt, der mir ne Hilfestellung geben kann... Vielen Dank!
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Mix die Farben selber.
Sollte eigentlich nicht schwer sein. Wenn du z.B. Rot mit einem Alpha von 128 (255 / 2) zeichnen willst, erhältst du als Rot(255, 128, 128).
Es dürfte also folgendes gelten:

Code: Alles auswählen

>>> from __future__ import division # Wichtig wenn Python 2 verwendet wird!
>>> class AlphaCalculator(object):
	def __init__(self, backr, backg, backb):
		self.backr = backr
		self.backg = backg
		self.backb = backb
	
	def calculate(self, r, g, b, a):
		r = (255 - a) / 255  * r  +  a / 255 * self.backr
		g = (255 - a) / 255  * g  +  a / 255 * self.backg
		b = (255 - a) / 255  * b  +  a / 255 * self.backb
		
		return (int(r), int(g), int(b))

	
>>> simulator = AlphaCalculator(255, 255, 255) # Hintergrundfarbe: weiß
>>> half_transparent_red = simulator.calculate(255, 0, 0, 128) # Rot mit einem Alpha von 128 (255 / 2)
>>> half_transparent_red
(255, 128, 128) # Ergebnis, verblasstes Rot
Gruß
Grüßle.
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Hallo Chris,

Vielen Danke für deine Mühe :)
Wenn ich deinen Code richtig verstehe, dann bezieht der sich immer auf den Hintergrund...
und erzeugt nur den schein, dass man transparent zeichnen würde...

ich möchte aber praktisch gesehen, eine scheibe anhauchen und mit dem finger reinzeichnen können, sodass ich wieder durch das fenster schauen kann...

(falls ich deinen code mißinterpretiert habe, fühl dich bitte genötigt mir zu widersprechen :))
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Naja, das bezog sich eher auf
The alpha value will be written directly into the Surface if it contains pixel alphas, but the draw function will not draw transparently.
Das kannst du halt dementsprechend anpassen. Ich dachte das Problem liegt daran, dass das Verblassen nicht klappt.

Beispiel: So sieht dein Bild vor dem verblassen aus (1):

Code: Alles auswählen

XXXXX
XXXXX
XXXXX
XXXXX
XXXXX
So in der Hälfte der Zeit (2):

Code: Alles auswählen

XXXXX
XXXXX
XX.XX
XXXXX
XXXXX
Und so am Ende des Vorgangs (3):

Code: Alles auswählen

XXXXX
XXXXX
XX#XX
XXXXX
XXXXX
Der Punkt stellt das halb-verblasste # dar.
Wenn deine Hintergrundfarbe beispielsweise weiß ist, die zu sichtbar machende Fläche Schwarz (der Punkte bzw. das #), und die nicht angehauchte Fläche ein Eisblau, dann gilt folgendes:
(1): Objekt = Eisblau
(2): Objekt = AlphaCalculator(Eisblau).calculate(0, 0, 0, 128)
(3): Objekt = Schwarz

Der Rest ist nur noch Code den du vervollständigen musst.
Wenn du das nicht meinst, musst du das Problem nochmal genauer beschreiben.

Gruß
Zuletzt geändert von theliquidwave am Mittwoch 5. Mai 2010, 14:12, insgesamt 1-mal geändert.
Grüßle.
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Ich hab mal was zusammengeschrieben, wenn das das ist was du meinst...
ich möchte also den weißen hintergrund wegmalen... um das bild zu sehen...
das ist mein wunschtraum ;-)
aller dings, und das ist das was ich meine... ich verändere ja nur die farbe meines malens...
und zeichne nicht "echt" transparent...

Code: Alles auswählen

#!/usr/bin/python
from __future__ import division # Wichtig wenn Python 2 verwendet wird!
import pygame

from pygame.locals import *



class AlphaCalculator(object):
	def __init__(self, backr, backg, backb):
		self.backr = backr
		self.backg = backg
		self.backb = backb
	  
	def calculate(self, r, g, b, a):
		r = (255 - a) / 255  * r  +  a / 255 * self.backr
		g = (255 - a) / 255  * g  +  a / 255 * self.backg
		b = (255 - a) / 255  * b  +  a / 255 * self.backb
	       
		return (int(r), int(g), int(b)) 


pygame.init()

def testDraw():

	#Create window
#	window = pygame.display.set_mode((1366, 768), pygame.FULLSCREEN)
	window = pygame.display.set_mode((600, 400) )
	pygame.display.set_caption('Test Drawing')
	screen = pygame.display.get_surface()
	background = pygame.Surface(screen.get_size())
	background.fill((255,255,255))

	_image = pygame.image.load("asd.jpg")# Das Bild welches hinter dem Hintergrund liegt
	_image.set_alpha(255)
	screen.blit(_image, (0, 0))

	screen.blit(background, (0,0))# Weißer Hintergrund, welcher auf dem Bild liegt...
	
	i = 0
		
	while True:

		for e in pygame.event.get():
			if e.type in (QUIT,KEYDOWN,MOUSEBUTTONDOWN):
				return

		if pygame.event.get():
			sim = AlphaCalculator(255,255,255)
			color = sim.calculate(0,0,0,150)
			pygame.draw.circle(screen, color, (pygame.mouse.get_pos()), 10, 0)
			#Update screen
			pygame.display.flip()
			i = i + 1


######## MAIN ##########

if __name__ == '__main__':

	testDraw()

	print "Done."
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Vielleicht bin ich ja festgefahren...
aber langsam weiß ich nicht mehr weiter...
hat noch keiner versucht transparent zu zeichnen?
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Das was du meinst ist nich Transparent zeichen, eher eine Ebene löschen.
Du musst dir bevor du dein Bild "übermalst" an welcher Stelle welche Farbe war, wenn du dann mit deinem "Finger" das Beschlagene weggwischst, musst die die gemerkten Farben wieder Setzten.
Mit einem dict, könnte das funktionieren.
the more they change the more they stay the same
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

das hab ich auch schon überlegt, aber das müsste ich mit jedem einzelnen pixel machen,
wenn zum beispiel ein bild der hintergrund ist... und ich kann mir nicht vorstellen, dass ich mehrere
"farben" in einem strich hinbekomme... sodass ich einfach nur die eigentilchen pixel nachmale...
gibt es sowas in gtk? dann schreib ich das um... ich muss mich auch damit mal befassen...
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Naja. Wieso nimmst du nicht einfach eine XY-Matrix?

Code: Alles auswählen

data = {}
data[0] = {}
data[0][0] = (255, 0, 0) # x:0 y:0
data[0][1] = (255, 0, 22) # x:0 y:1
data[1][0] = (0, 255, 0) # x:1 y:0
# ...
Musst du halt mit einer for-Schleife machen ;)

Gruß
Grüßle.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Chrisber:

Code: Alles auswählen

>>> data = {}
>>> data[0] = {}
>>> data
{0: {}}
>>> data[0][0] = 255, 0, 0
>>> data
{0: {0: (255, 0, 0)}}
>>> data[0][1] = 255, 0, 25
>>> data
{0: {0: (255, 0, 0), 1: (255, 0, 25)}}
>>> data[1][0] = 0, 255, 0
Traceback (most recent call last):
  File "<input>", line 1, in <module>
KeyError: 1
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

@chrisber... ich freu mich, dass sich jmd aktiv mit mir unterhält :) .... wollte ich nur mal gesagt haben ;)

hmmm, stellt das data array dann das bild dar, sprich jeden einzelnen pixel?
dann müsste ich das ja vorher auslesen können...noch dazu müsste ich dann
von der position der maus, das jeweilige pixel ableiten können... im fullscreen sicher
noch machbar, aber variabel?
ich glaube nicht... würde das dann nicht auch einen ziemlichen overhead erzeugen?
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Du hast mich aber auf eine Idee gebracht und ich hab mal nen prototypen geschrieben...
ich verfolge nun eine andere technik... allerdings ist das kein malen mehr...
sondern eher einfaches "ausblenden" ander jeweiligen stelle... als workaround...
vielleicht fällt da jmd was ein, wie ich es schaffen könnte, dass ich statt des lokalen ausblendens...
eine art zeichnen emulieren kann...?

Code: Alles auswählen

import pygame

screen = pygame.display.set_mode((1000,500))
blueSquare = pygame.Surface((100,100))
blueSquare.fill((0,0,255))
redSquare = pygame.Surface((100,100))
redSquare.fill((255,0,0))
redSquare.set_colorkey((0,0,1))
column = pygame.Surface((20,20))
column.fill((0,0,1))

columnx = 0
columnAdd = 1

myClock = pygame.time.Clock()
running = True
while running:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT or event.type == pygame.KEYDOWN and
            event.key == pygame.K_ESCAPE):
            running = False
    screen.fill((255,255,255))
    redSquare.fill((255,0,0))
    redSquare.blit(column,(pygame.mouse.get_pos()))
    screen.blit(blueSquare,(50,50))
    screen.blit(redSquare,(0,0))
    pygame.display.flip()
    myClock.tick(40)

    columnx += columnAdd
    if columnx >= 80 or columnx < 0:
        columnAdd *= -1
majinv
User
Beiträge: 42
Registriert: Mittwoch 14. April 2010, 13:21

Aloah, falls das Thema von jemandem anderen gesucht wird, mein letzter prototyp...
es ist noch nicht optimal, geht aber in die richtung die ich haben wollte, sollte jemand einen
weg über die drawing methode von pygame finden, das gleiche ziel zu erreichen, wäre ich mehr als
nur begeistert es hier zu lesen...

viele grüße
majin

Code: Alles auswählen

import pygame

screen = pygame.display.set_mode((1000,500))
blueSquare = pygame.Surface((300,300))
blueSquare.fill((0,0,255))
redSquare = pygame.Surface((300,300))
redSquare.fill((255,0,0))
redSquare.set_colorkey((0,0,1))
brush = pygame.Surface((10,10))
brush.fill((0,0,1))

painting = False

running = True
while running:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT or event.type == pygame.KEYDOWN and
            event.key == pygame.K_ESCAPE):
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            painting = True
        if event.type == pygame.MOUSEBUTTONUP:
            painting = False
    if painting:
        redSquare.blit(brush,pygame.mouse.get_pos())
   
    screen.fill((255,255,255))
    screen.blit(blueSquare,(50,50))
    screen.blit(redSquare,(0,0))
    pygame.display.flip()
Antworten