สไปรท์หมายถึงอะไร? สไปรต์ CSS ข้อดีของการใช้สไปรท์

อุตสาหกรรมคอมพิวเตอร์ใน ปีที่ผ่านมาสูงขึ้นมาก สูงมาก หากเกมคอมพิวเตอร์ก่อนหน้านี้เป็นเพียงความบันเทิงสำหรับแฟน ๆ ในวงแคบ ตอนนี้เกมเหล่านั้นก็เป็นอะไรที่มากกว่านั้น สามารถเล่นได้กับคนทุกวัย และโปรเจ็กต์ก็ถูกสร้างขึ้นที่เหมาะกับรสนิยมที่ละเอียดอ่อนที่สุด และที่สำคัญที่สุดคือพวกเขาปรากฏตัวขึ้น โอกาสอันเหลือเชื่อซึ่งก่อนหน้านี้คิดไม่ถึง ดังนั้นตอนนี้เกมคอมพิวเตอร์จึงสามารถแยกไม่ออกจากความเป็นจริงในแง่ของกราฟิกและฟิสิกส์ พวกเขาสามารถดื่มด่ำกับผู้ใช้ในโลกที่ไม่รู้จัก ทำให้เขามีชีวิตเรื่องราวที่น่าทึ่งและเป็นตัวละครหลักในนั้น แต่ในขณะเดียวกัน บางคนไม่ต้องการถูกจำกัดอยู่เพียงกระบวนการ "เล่น" - พวกเขารู้สึกทึ่งกับขั้นตอนการสร้างเกม อย่างไรก็ตาม นักฝันเหล่านี้ส่วนใหญ่ยังคงอยู่ในระดับจินตนาการ เพราะพวกเขาเชื่อเช่นนั้น กระบวนการนี้ซับซ้อนเกินไป ในความเป็นจริง มันไม่ได้เป็นเช่นนั้น ดังที่เห็นได้จากนักพัฒนาอินดี้จำนวนมากที่ปัจจุบันผลิตโปรเจ็กต์จำนวนมากโดยไม่มีงบประมาณจำนวนมากหรือได้รับการสนับสนุนจากผู้จัดพิมพ์ คุณเพียงแค่ต้องเริ่มต้นจากจุดเล็กๆ และค่อยๆ ก้าวไปข้างหน้า ในบทความนี้ คุณจะได้เรียนรู้ว่าสไปรต์เกมคืออะไรและใช้งานอย่างไร เพื่อให้คุณสามารถเริ่มสร้างโปรเจ็กต์ของคุณเองได้

สไปรท์คืออะไร?

หากคุณมีเกมคอมพิวเตอร์อยู่บนจอ คุณเห็นอะไรตรงหน้าคุณ? เปลือกกราฟิก โครงการนี้พื้นผิวต่างๆ ที่ประกอบด้วยพิกเซลเล็กๆ หากคุณกำลังวางแผนที่จะสร้างเกมคอมพิวเตอร์ คุณจะต้องทำงานกับกราฟิกเป็นจำนวนมาก แต่ถ้าคุณยังไม่ได้ลงมือทำ โครงการสำคัญคุณไม่จำเป็นต้องทำงานกับโปรแกรมแก้ไขกราฟิก 3D ได้อย่างสมบูรณ์แบบ สไปรท์สำหรับเกมที่คุณสามารถดาวน์โหลดบนอินเทอร์เน็ตจะช่วยคุณได้ที่นี่ แต่มันคืออะไร? จะนำไปใช้ได้อย่างไรและจะทำให้งานของคุณง่ายขึ้นได้อย่างไร? สไปรต์เกมเป็นพื้นผิวสำเร็จรูปของตัวละคร วัตถุ ฯลฯ ที่คุณสามารถดาวน์โหลดลงในคอมพิวเตอร์ของคุณ แล้วใช้ในกระบวนการสร้างเกม ซึ่งหมายความว่าคุณไม่จำเป็นต้องวาดทุกวัตถุในเกม เช่นเดียวกับทุกขั้นตอนของการเคลื่อนที่ - คุณจะมีทุกอย่างอยู่แล้ว แบบฟอร์มเสร็จแล้ว- อย่างที่คุณเห็น สไปรต์ของเกมสามารถทำให้ชีวิตของคุณง่ายขึ้นมาก

สไปรท์วิว

ตอนนี้คุณมี ความคิดทั่วไปเกี่ยวกับสไปรท์สำหรับเกม แต่ไม่เพียงพอต่อการใช้ในทางปฏิบัติ เราจำเป็นต้องค้นหาว่ามันคืออะไรและจะนำไปใช้ในการสร้างเกมได้อย่างไร หากคุณกำลังจะใช้สไปรท์ คุณจะต้องดาวน์โหลดสไปรท์ลงในคอมพิวเตอร์ของคุณ ในกรณีส่วนใหญ่จะดูใหญ่หรือใหญ่โตด้วยซ้ำ ไฟล์กราฟิกซึ่งรูปภาพขนาดเล็กหลายสิบหรือหลายร้อยภาพจะอยู่บนพื้นหลังโปร่งใส ดังนั้นคุณสามารถตัดสิ่งนี้ได้ ไฟล์ขนาดใหญ่สำหรับเด็กเล็กเพื่อเข้าถึงสไปรท์ของคุณได้โดยตรง คุณอาจไม่จำเป็นต้องใช้บางส่วนและสามารถตัดออกได้ ดังนั้นวิธีนี้จึงสะดวกกว่าการดาวน์โหลดภาพหลายสิบหรือหลายร้อยภาพ คุณเพียงแค่เลือกไฟล์ขนาดใหญ่ ทำเครื่องหมายพื้นที่ และคุณก็จะได้สไปรท์

การใช้สไปรท์

ดังที่คุณทราบดี ในกรณีส่วนใหญ่ คุณจะสามารถค้นหาสไปรท์สำหรับเกม 2 มิติได้ เนื่องจากภาพ 3 มิติไม่ได้มาตรฐาน ดังนั้น จึงต้องใช้พื้นที่มากในการถ่ายทอดการเคลื่อนไหวทั้งหมดของสิ่งหนึ่ง วัตถุสามมิติ- ในขณะเดียวกัน การทำงานกับสไปรต์ 2 มิติก็ทำได้ง่ายมาก คุณเพียงแค่โหลดสไปรท์ลงในโปรแกรมแก้ไขที่คุณกำลังสร้างและต่อเข้าด้วยกันเพื่อสร้างเอฟเฟกต์การเคลื่อนไหว จากนั้นโหลดมันลงในระดับและเพลิดเพลินไปกับผลลัพธ์

การเปลี่ยนจากสไปรท์เป็นกราฟิก

คุณจะไม่สามารถใช้สไปรท์เพื่อสร้างเกมได้ตลอดชีวิต ดังนั้นหากคุณมีความทะเยอทะยาน คุณจะต้องเรียนรู้วิธีใช้สไปรท์เหล่านั้นหรือหาใครสักคนมาช่วยคุณเกี่ยวกับทักษะนี้

สไปรท์ค่อนข้างน่าสนใจและ เทคโนโลยีที่เรียบง่าย- ตอนนี้ฉันจะบอกคุณเพิ่มเติมเล็กน้อยเกี่ยวกับเรื่องนี้

CSS สไปรต์คืออะไร?

สั้นๆ แล้ว. สไปรต์ CSSเหล่านี้เป็นภาพหลายภาพในไฟล์เดียว มีไฟล์เดียวแต่มีหลายภาพอยู่ข้างใน ในเวลาเดียวกันผู้เยี่ยมชมจะมองไม่เห็นสิ่งนี้โดยสิ้นเชิง สำหรับคนที่กำลังดูไซต์นี้ ดูเหมือนว่าเขาจะเห็นภาพหลายภาพแยกกัน

เหตุใดจึงจำเป็น? สไปรท์ลดจำนวนคำขอไปยังเพจจากผู้ใช้และลด ขนาดโดยรวมภาพ ส่งผลให้ผู้เยี่ยมชมเห็นเว็บไซต์เร็วขึ้น

วิธีนี้ทำอย่างไร? รูปภาพธรรมดาจะเพิ่มความกว้างและความสูง กล่าวคือ รูปภาพหลายรูปจะถูกวางเรียงกันบนรูปภาพธรรมดา แล้วทุก แยกภาพจากชุดนี้จะถูกแทนที่เป็น บล็อกที่จำเป็นด้วยความกว้างหรือความสูงที่กำหนดเพื่อไม่ให้มองเห็นภาพอื่นๆ ทั้งหมด ครอปทั้งชุดและเหลือเพียงภาพเดียว สไปร์ทตัวหนึ่ง รูปภาพอื่นๆ ทั้งหมดยังคงอยู่นอกบล็อกเฉพาะ

เพื่อให้ชัดเจนยิ่งขึ้นฉันจะเปรียบเทียบ ลองจินตนาการว่าคุณกำลังมองผ่านรูกุญแจ คุณเห็นเพียงบางส่วนของห้องที่แยกจากกันที่อีกด้านหนึ่งของประตู หากคุณขยับไปทางด้านข้างเล็กน้อยแล้วมองเข้าไปในถ้ำจากมุมที่ต่างออกไป คุณจะเห็นส่วนอื่นๆ ของห้องเดียวกัน

คำศัพท์เฉพาะทาง

เพื่อหลีกเลี่ยงความสับสน เรามานิยามคำศัพท์กันทันที:
เทพดา- นี่คือหนึ่งภาพจากไฟล์ที่มีหลายภาพ
ชุดสไปรท์เป็นไฟล์ที่มีรูปภาพหลายรูป

คุณสมบัติของการใช้สไปรท์

เมื่อใดที่คุณควรใช้สไปรท์? โดยทั่วไปมีคำตอบเดียวคือ ควรใช้สไปรท์หากคุณมีรูปภาพขนาดเล็กจำนวนมากบนหน้าเว็บ มันไม่สำคัญว่ามันจะเป็นภาพประเภทไหน หากคุณมีการไล่ระดับสีจำนวนมากในตำแหน่งเดียวกัน มีปุ่มจำนวนมาก ไอคอนจำนวนมาก ฯลฯ ถ้าด้วยเหตุผลบางอย่าง หน้าแยกกันมีรูปภาพเล็กๆ จำนวนมาก คุณอาจลองใช้สไปรท์ดู

โดยปกติแล้วจะมีรูปภาพสามประเภทบนหน้าเว็บ - jpg, png และ gif รูปแบบทั้งหมดเหล่านี้มีโหมดการดาวน์โหลดสองโหมด - โหมดปกติและโหมดการดาวน์โหลดแบบค่อยเป็นค่อยไป

รูปแบบ jpg อาจเป็นแบบปกติ (พื้นฐาน) หรือแบบก้าวหน้า (แบบก้าวหน้า) ใน โหมดปกติรูปภาพเริ่มแสดงทีละบรรทัดขณะโหลดและทันที คุณภาพดี- ในโหมดโปรเกรสซีฟ รูปภาพ jpgถูกโหลดทันทีอย่างครบถ้วน แต่ใน คุณภาพไม่ดีและในขณะที่โหลด คุณภาพก็จะเพิ่มขึ้น

Gif และ PNG มีพฤติกรรมเหมือนกัน GIF อาจเป็นแบบปกติหรือแบบอินเทอร์เลซก็ได้ PNG อาจเป็นแบบปกติหรือแบบอินเทอร์เลซก็ได้ พฤติกรรมของ gif และ png แบบอินเทอร์เลซนั้นคล้ายคลึงกับพฤติกรรมของ JPG แบบก้าวหน้า- ลักษณะการทำงานนี้จะเพิ่มขนาดไฟล์เล็กน้อย

ทั้งหมด.รูปภาพอาจปรากฏบนเพจทันทีหรืออาจปรากฏขึ้นโดยมีความล่าช้า นี่เป็นสิ่งสำคัญที่ต้องรู้เมื่อพูดถึงสไปรท์ ขอแนะนำให้สร้างสไปรท์แบบอินเทอร์เลซหรือแบบก้าวหน้า ผู้ใช้ควรเห็นภาพโดยเร็วที่สุด แม้ว่าจะมีคุณภาพต่ำก็ตาม

แต่!ถ้า ไฟล์สุดท้ายเนื่องจากสไปรท์ทั้งหมดจะมีขนาดใหญ่เกินไป แม้จะมีความก้าวหน้าและการอินเทอร์เลซ แต่ผู้เยี่ยมชมจะต้องรอแม้จะดาวน์โหลดไฟล์เพียงบางส่วนก็ตาม ดังนั้นฉันไม่แนะนำให้ใช้สไปรท์ชุดใหญ่ หากไฟล์มีขนาดใหญ่สไปรท์ทั้งหมดจะหายไปโดยสิ้นเชิง - เพื่อเร่งความเร็วไซต์ เมื่อใช้สไปรท์ชุดใหญ่ ผู้ใช้จะต้องรอนานกว่าการแยกภาพปกติ

ไฟล์ที่มีขนาดเกิน 30 กิโลไบต์ดูเหมือนใหญ่สำหรับฉัน นี่เป็นเรื่องส่วนตัว คุณอาจมีแนวคิดเกี่ยวกับขนาดของไฟล์เป็นของตัวเอง ไฟล์ขนาด 30 กิโลไบต์จะดาวน์โหลดไฟล์ในเวลาประมาณ 7 วินาที ด้วยความเร็วอินเทอร์เน็ต 56.6 kbps

ตัวอย่างการใช้สไปรท์

สไปรท์พร้อมไอคอน

ในสไปรท์หนึ่ง ฉันจะมีไอคอนสำหรับ:

  1. รายการ - หนึ่งไอคอน
  2. ลิงค์ - สามไอคอน
  3. แบบฟอร์มการค้นหา - ไอคอนเดียว

นั่นคือสไปรท์ชุดแรกของฉันจะมีห้ารูปภาพ รูปภาพของฉันทั้งหมดจะมีขนาดเท่ากัน - 16 x 16 พิกเซล สไปรท์สามารถใช้สร้างภาพที่มีความละเอียดต่างกันได้ โดยไม่จำเป็นว่าความละเอียดของภาพทั้งหมดจะตรงกัน ที่ ความละเอียดที่แตกต่างกันรูปภาพ จะซับซ้อนกว่าเล็กน้อยในการรวมรูปภาพเหล่านี้เป็นไฟล์เดียว

ด้วยเหตุนี้ ตัวอย่างแรกจะมีลักษณะดังนี้:

ฉันพบห้าไอคอน จากนั้นฉันก็รวมพวกมันทั้งหมดไว้ในไฟล์เดียว นี่คือไฟล์ที่ฉันลงเอยด้วย:

ฉันดึงความสนใจของคุณ ใน ในกรณีนี้ไอคอนไม่ได้อยู่ใกล้กัน แต่มีรอยเยื้องเล็กน้อยระหว่างกัน จะเลือกเยื้องเหล่านี้ได้อย่างไร? แน่นอนคุณสามารถคำนวณทุกอย่างแบบพิกเซลต่อพิกเซลได้ แต่กรณีของเราค่อนข้างง่าย ดังนั้นทางที่ดีที่สุดคือเลือกการเยื้องเหล่านี้ในภาพโดยการทดลอง ขั้นแรก เรารวมภาพเข้าด้วยกันโดยใช้สายตา จากนั้นเราจะถ่ายภาพบนสุดและวางไว้ในตำแหน่งที่ถูกต้อง หากรูปภาพอยู่ในตำแหน่งเดิม แต่ในขณะเดียวกันก็มีรูปภาพอีกชิ้นหนึ่งยื่นออกมาจากที่ใดที่หนึ่ง จะต้องเพิ่มการเยื้อง

อีกสิ่งหนึ่ง สุดท้ายในรายการคือไอคอนสำหรับรายการ - ลูกศรสีเขียว- ทำไมเธอถึงเป็นคนสุดท้าย? ตำแหน่งของไอคอนที่เหลืออยู่ในรูปภาพนั้นไม่แยแสกับเรา แต่ในรายการรายการใด ๆ สามารถครอบครองได้หลายบรรทัดและหากลูกศรสีเขียวอยู่ตรงกลางแสดงว่า บรรทัดต่อไปนี้ภาพอื่นๆก็จะโดดเด่นออกมา ดูภาพรายการด้านบนเพื่อดูว่าฉันกำลังพูดถึงอะไร

ดังนั้น. ฉันพบไอคอนห้าไอคอนและรวมเป็นไฟล์เดียว เราจะทำอย่างไรต่อไป? แน่นอนเราเขียนโค้ด:

  • รายการ
  • อีกหนึ่งรายการครับ
  • รายการ
  • อีกหนึ่งรายการครับ
    แต่เป็นสองบรรทัด
  • รายการ
  • อีกหนึ่งรายการครับ

นี้ รหัสเอชทีเอ็มรายการ. ตอนนี้ลองใช้สไปรท์ของเรากับมัน:

Ul li( ช่องว่างภายใน:0 0 0 21px; พื้นหลัง:url("sprites.png") 0 -94px ไม่ทำซ้ำ; )

เราทำอะไรที่นี่? เยื้องแต่ละอัน

  • ห่างจากขอบด้านซ้าย 21 พิกเซล เพื่อให้ข้อความไม่บดบังรูปภาพ จากนั้นตั้งค่า sprites.png เป็นภาพพื้นหลัง ความสูงของรูปภาพทั้งหมดที่มีสไปรท์ในกรณีนี้คือ 110 พิกเซล และลูกศรสีเขียวอยู่ที่ส่วนท้ายสุด ความสูงของลูกศรสีเขียวคือ 16 พิกเซล นั่นคือลูกศรเริ่มต้นหลังจากพิกเซลที่ 94 จากด้านบนของรูปภาพ ซึ่งหมายความว่าเราต้องย้ายพื้นหลังขึ้น 94 พิกเซล ใน รหัส CSSมันเขียนแบบนี้ "0 -94px" นั่นคือย้าย 0 พิกเซลไปทางขวาและ 94px พิกเซลขึ้น

    มาปิดท้ายด้วยรายการ ตอนนี้เรามาสร้างลิงก์ในลักษณะเดียวกันโดยประมาณ:

    A( ช่องว่างภายใน:0 0 0 20px; พื้นหลัง:url("sprites.png") 0 -42px ไม่ทำซ้ำ; ) a( ช่องว่างภายใน:0 0 0 20px; พื้นหลัง:url("sprites..png") 0 -21px ไม่ซ้ำ)

    ตัวเลือกหมายถึงอะไร? เห็นได้ชัดว่าตัวเลือกนี้บังคับให้เบราว์เซอร์ใช้สไตล์นี้กับลิงก์ทั้งหมดที่มีแอตทริบิวต์ href ซึ่งค่าขึ้นต้นด้วยสตริง http://site/ สไปรท์นั้นถูกใช้ในลักษณะเดียวกับในกรณีของรายการ ฉันจะพิจารณาลิงก์เดียวเท่านั้น - ลิงก์ไปยังบล็อกของฉัน

    1. เรากำหนด ลิงค์ที่ต้องการโดย href.. คุณสามารถกำหนดคลาสให้กับลิงก์ที่ต้องการหรือเพิ่มสไตล์ให้กับแอตทริบิวต์ style ได้โดยตรงในโค้ด html หรือระบุลิงค์ที่ต้องการโดยใช้วิธีอื่น
    2. เราสร้างระยะขอบ 20 พิกเซลจากขอบด้านซ้ายของลิงก์ใดลิงก์หนึ่ง
    3. ระบุรูปภาพ sprites.png เป็นภาพพื้นหลัง
    4. รูปภาพที่ฉันเลือกสำหรับบล็อกคือ 21 พิกเซลจากขอบด้านบน ซึ่งหมายความว่าเราต้องย้ายพื้นหลังลง 21 พิกเซล ใน css ฉันเขียนแบบนี้: “0 -21px”

    การบ้าน

    สไปรท์ที่มีการไล่ระดับสี

    ตอนนี้เรามาดูตัวอย่างที่สองกัน


    ภาพนี้แสดงหน้าต่าง หน้าต่างมีส่วนหัว เนื้อหา และส่วนท้าย แต่ละองค์ประกอบเหล่านี้มีการตั้งค่าการไล่ระดับสีพื้นหลังไว้ หากไม่สามารถมองเห็นได้ในทันที มีการเปลี่ยนสีจากสีซีดไปเป็นสีอิ่มตัว

    ฉันจะแสดงให้คุณเห็นว่าการไล่ระดับสีในหน้าต่างนี้สามารถสร้างเป็นสไปรท์ได้อย่างไร ส่วนหัวและส่วนท้ายของหน้าต่างจะมีความสูงคงที่ - 30 พิกเซล ตัวหน้าต่างจะยืดออกขึ้นอยู่กับความยาวของข้อความ

    ตอนนี้เรามาเขียนโค้ด html สำหรับหน้าต่างกัน:

    มาเริ่มใช้สไปรท์กันเถอะ เริ่มจากชื่อหน้าต่างกันก่อน:

    #window-header( ความสูง:30px; พื้นหลัง:#C0C0FF url("gradients.png") 0 0 ซ้ำ-x; )

    ในไฟล์ gradients.png ขั้นแรกจะมีการไล่ระดับสีสำหรับส่วนหัว จากนั้นสำหรับเนื้อหา จากนั้นจึงสำหรับ บรรทัดล่าง- นั่นคือการไล่ระดับสีสำหรับชื่อเรื่องเริ่มต้นจากด้านบนสุด ดังนั้นเราจึงเพียงแค่ตั้งค่าไฟล์ให้เป็นพื้นหลังและระบุตำแหน่งเป็น "0 0" นั่นคืออย่าถอยไปไหนเลย หากต้องการทำให้การไล่ระดับสียืดออกในแนวนอน ให้เขียนว่า "repeat-x"

    เพื่อให้แน่ใจว่าการไล่ระดับสีทั้งหมดพอดีกับส่วนหัว ให้ตั้งค่าความสูงเป็น 30 พิกเซล

    มาตั้งค่าการไล่ระดับสีสำหรับส่วนท้ายในลักษณะเดียวกับส่วนหัว:

    #window-footer( ความสูง:30px; พื้นหลัง: #C0FFC0 url("gradients.png") 0 -60px ซ้ำ-x; )

    เฉพาะครั้งนี้เราจะย้ายรูปภาพลง 60 พิกเซล

    สถานการณ์กับตัวหน้าต่างนั้นซับซ้อนกว่า ร่างกายของเราจะยืดไม่เหมือนกับส่วนหัวและส่วนท้าย นั่นคือ ถ้าเราสร้าง div หนึ่งรายการสำหรับตัวหน้าต่างและใส่การไล่ระดับสีที่นั่น การไล่ระดับสีทั้งหมดจะปรากฏใน div นี้พร้อมกัน อีกทางหนึ่ง เราสามารถใส่การไล่ระดับสีสำหรับเนื้อหาเป็นแนวตั้ง แต่จะเกิดอะไรขึ้นถ้าเรามีการไล่ระดับสีหลายแบบสำหรับบล็อกที่ยืดออก? คุณไม่สามารถทำทุกอย่างได้ในคราวเดียว เราจะทำให้มันฉลาดขึ้นอีกหน่อย

    รหัส CSS จะเป็นดังนี้:

    #window-body( ตำแหน่ง:ญาติ; ) #window-body-gradient( ตำแหน่ง:สัมบูรณ์; ซ้าย:0; บน:0; ความกว้าง:100%; ความสูง:30px; พื้นหลัง:url("gradients.png") 0 - 30px ซ้ำ-x; ) #window-body-text( ตำแหน่ง: ญาติ; )

    ตอนนี้ฉันจะบอกคุณโดยละเอียดมากขึ้นว่าเราทำอะไรที่นี่ นี่คือโค้ด html ของตัวหน้าต่างแยกกัน:

    อย่างที่คุณเห็น เรามีนักร้องอีกสองคนฝังอยู่ในร่างกาย "การไล่ระดับสีของ windows-body-" แรกจะเป็นผู้รับผิดชอบในการไล่ระดับสี “window-body-text” ที่สองใช้สำหรับข้อความ นอกจากนี้ ตามที่เห็นชัดเจนจากโค้ด CSS เราใช้ตำแหน่ง: ญาติ; สำหรับทั้งตัวหน้าต่าง

    สำหรับ div การไล่ระดับสี เราระบุตำแหน่ง:สัมบูรณ์ ดังนั้นเราจึงทำให้ div การไล่ระดับสีออกจากโฟลว์ทั่วไป ตอนนี้ div นี้ไม่มีผลกับสิ่งใดเลย เนื่องจากเราได้ระบุตำแหน่ง: สัมพันธ์กับทั้งเนื้อหา div การไล่ระดับสีจึงไม่ลอยไปไกลกว่าตำแหน่งแม่ ติดไว้ที่ขอบด้านซ้ายและด้านบนของตัวหน้าต่างโดยใช้ “left:0; บนสุด:0;". ตั้งค่าความสูงของ div การไล่ระดับสีเป็น 30 พิกเซล นั่นคือ ในกรณีนี้ เราจะระบุความสูงของการไล่ระดับสีที่เราจะแนบไว้ หากความสูงของ div มากกว่าความสูงของการไล่ระดับสี สไปรท์อื่นๆ จะโผล่ออกมาใน div และสุดท้าย เราก็แนบไฟล์ การไล่ระดับสี.png ของเราเข้ากับ div การไล่ระดับสี ตามปกติ เราจะย้ายพื้นหลังขึ้นตามระยะทางที่ต้องการ ในกรณีนี้ เราจะย้ายพื้นหลังขึ้น 30 พิกเซล

    ตอนนี้เรามีการไล่ระดับสีในเนื้อความของหน้าต่าง แต่มันบดบังข้อความ เพื่อป้องกันไม่ให้ข้อความถูกบดบัง เราจะล้อมข้อความทั้งหมดไว้ใน div และกำหนดตำแหน่งให้สัมพันธ์กัน เมื่อกำหนดแล้ว ข้อความจะอยู่ด้านบนของการไล่ระดับสี

    นั่นคือทั้งหมด ตอนนี้เราได้วางการไล่ระดับสีทั้งหมดไว้ในหน้าต่างของเราแล้ว และในส่วนหัวและในร่างกายและในห้องใต้ดิน

    ฉันอธิบายยาวมากเพื่อให้ทุกอย่างชัดเจน แต่ในความเป็นจริง หากคุณรู้เพียงเล็กน้อยเกี่ยวกับเลย์เอาต์ ก็อาจจะเพียงพอแล้วสำหรับคุณที่จะดูตัวอย่างด้วยตนเอง:

    ฉันทำซ้ำลิงก์อีกครั้ง

    ที่จริงแล้ว คุณสามารถมีตัวอย่างการใช้สไปรท์ได้มากมาย ฉันแสดงตัวอย่างเพียงสองตัวอย่างเท่านั้น แต่ตัวอย่างเหล่านี้น่าจะเพียงพอที่จะเข้าใจวิธีการทำงานของสไปรท์ หากคุณมีคำถามใด ๆ ถามในความคิดเห็น

    การแนะนำ

    ก่อนอื่นคุณต้องหาก่อนว่าสไปรท์คืออะไร ฉันพบคำอธิบายนี้ในหนังสือของอังเดร ลา โมตา:

    “รู้มั้ย มีน้ำอัดลมแบบนี้... ฉันล้อเล่นอีกแล้ว จริงๆ แล้วสไปรท์เป็นวัตถุเล็กๆ ที่อยู่บนสนามเด็กเล่นและสามารถเคลื่อนไหวได้ คำนี้หยั่งรากมาจาก มือเบาโปรแกรมเมอร์จาก Atari และ Apple ในช่วงกลางทศวรรษที่ 70 สไปรท์เป็นตัวละครในเกมพีซีที่สามารถเคลื่อนที่ไปรอบๆ หน้าจอ เปลี่ยนสีและขนาดได้อย่างง่ายดาย”

    ดังนั้นสไปรท์จึงเป็นตัวละครในเกม โดยไม่ต้องเจาะลึกเข้าไปในป่าของการเขียนโปรแกรม ฉันสามารถพูดได้ว่าสไปรท์นั้นเป็นอาร์เรย์ของสี - สำหรับต่อมลูกหมาก ลองจินตนาการว่ามันเป็นไฟล์ BMP หรือ TBitmap โดยเฉพาะอย่างยิ่งเนื่องจากรูปแบบนี้รองรับโดย Windows และไม่มีการบีบอัด

    สิ่งที่เราต้องการจากสไปรท์คือการทำให้มันปรากฏบนหน้าจอและสร้างภาพเคลื่อนไหว แอนิเมชั่นไม่เพียงแต่เป็นการเปลี่ยนแปลงพิกัดของสไปรท์เท่านั้น แต่ยังรวมถึงการเปลี่ยนแปลงในตัวภาพด้วย ดังนั้นสไปรท์จึงไม่สามารถมีภาพเดียวได้ แต่มีหลายภาพ การเปลี่ยนแปลงนำไปสู่แอนิเมชั่น

    อย่างที่ฉันบอกไปแล้ว สไปรท์ก็คือเมทริกซ์ เมื่อประกอบเข้ากับสี่เหลี่ยมจัตุรัส (สี่เหลี่ยม) วัตถุที่ซับซ้อนเช่นตัวช่วยจากภาพด้านล่างมีพื้นที่ว่างเหลืออยู่ มันเต็มไปด้วยสีที่ไม่ได้อยู่ในภาพของวัตถุนั้นเอง เพียงคัดลอกเมทริกซ์นี้ (หรือ BMP หรือ TBitmap เพื่อความง่าย) จะแสดงทั้งตัวช่วยสร้างและพื้นหลังด้านล่าง แต่เราไม่ต้องการสิ่งนี้เสมอไป ขอย้ำว่าไม่เสมอไป หากสไปรท์ปรากฏบนพื้นหลัง มันจะลบพื้นที่สี่เหลี่ยมทั้งหมด

    ไม่มีความแตกต่างและค่อนข้างชัดเจนใช่ไหม? เมื่อแสดงบนหน้าจอจะใช้รูปภาพเดียวกันแต่ทั้งหมดขึ้นอยู่กับวิธีการแสดงสไปรท์

    วิธีที่ 1 (นักมายากลในสี่เหลี่ยมสีขาว) นั้นมีพื้นฐานมาจากการคัดลอกพื้นที่หน่วยความจำหนึ่งไปยังอีกพื้นที่หนึ่ง

    วิธีที่ 2 (นักมายากลเบื้องหลัง) เลียนแบบเหมือนกันแต่ฉลาด การคัดลอกเกิดขึ้นโดย ไปยังอัลกอริธึมต่อไปนี้: หากสีขององค์ประกอบเมทริกซ์ที่คัดลอก (พื้นที่หน่วยความจำ) สอดคล้องกับค่าสีสีโปร่งใส ไม่มีการคัดลอกเกิดขึ้น เราจะไปยังองค์ประกอบถัดไป

    วิธีที่ 3 ก็ขึ้นอยู่กับการคัดลอกพื้นที่หน่วยความจำ แต่ใช้ การดำเนินการเชิงตรรกะ- มาสก์

    สไปรท์พร้อมหน้ากากสำเร็จรูป

    มีหลายวิธีในการแสดงสไปรท์บนพื้นผิวหน้าจอ ลองพิจารณาหนึ่งในนั้น นี่เป็นวิธีการวาดสไปรท์และมาสก์แยกกัน ในการทำเช่นนี้ เราจำเป็นต้องมีสไปรท์เอง รวมถึงมาสก์และบัฟเฟอร์ของมัน

    เทพดา
    หน้ากากสไปรท์

    ทั้งสไปรท์และมาส์กต้องมีขนาดเท่ากัน นิ้ว ในตัวอย่างนี้ 50x50. หน้ากากมีไว้เพื่ออะไร? จำเป็นเพื่อให้เมื่อมีการแสดงสไปรท์ รูปภาพที่อยู่ใต้สไปรท์จะไม่ถูกเขียนทับ คุณสามารถเตรียมมาสก์แยกต่างหากในไฟล์ BMP ซึ่งเป็นวิธีที่เร็วกว่าหรือคำนวณโดยทางโปรแกรมก็ได้

    ตัวช่วยสร้าง:=Tbitmap.Create; Wizard.Loadfromfile("spr1.bmp"); // บิตแมปสำหรับสไปรต์ WizardMask:=Tbitmap.Create; WizardMask.Loadfromfile("spr2.bmp"); // บิตแมปสำหรับมาสก์

    เรามีสไปรท์ หน้ากาก และเราต้องแสดงมันบนหน้าจอ มีฟังก์ชัน Win32Api สำหรับสิ่งนี้:

    BitBlt(param_1,X1,Y1,dX1,dY1,param_2,X2,Y2,param_3);

    • Param_1 - จัดการกับพื้นผิวที่จะแสดง
    • X1,Y1 - ออฟเซ็ตจากจุดเริ่มต้น
    • dX1,dY1 - ขนาดของภาพที่แสดง
    • Param_2 - จัดการตำแหน่งที่จะรับมัน
    • X2,Y2 - ขนาดของภาพที่แสดง
    • Param_3 - คัดลอกพารามิเตอร์

    สำหรับกรณีของเรา:

    BitBlt(Buffer.Canvas.Handle,X,Y,50,50, WizardMask.Canvas.Handle,0,0,SrcPaint); BitBlt(Buffer.Canvas.Handle,X,Y,50,50, Wizard.Canvas.Handle,0,0,SrcAnd);

    • SrcPaint - คัดลอกเฉพาะสีขาว
    • SrcAnd - คัดลอกทุกอย่างยกเว้นสีขาว

    ขั้นแรก เราจะแสดงมาสก์ด้วยพารามิเตอร์ SrcPaint จากนั้นในตำแหน่งเดียวกัน (พิกัด X,Y) สไปรท์เองด้วยพารามิเตอร์ SrcAnd

    ยังคงต้องพิจารณาว่าเหตุใดจึงจำเป็นต้องใช้บัฟเฟอร์ เมื่อแสดงสไปรท์ตัวหนึ่ง คุณจะไม่รู้สึกถึงการกะพริบของภาพ แต่เมื่อมีจำนวน 100-200 ตัว ก็จะสังเกตเห็นได้ชัดเจน ดังนั้น สไปรท์ทั้งหมดจะถูกคัดลอกไปยังบัฟเฟอร์ - นี่คือ Tbitmap ขนาดของหน้าจอหรือหน้าต่าง ซึ่งสั้นกว่าพื้นที่ที่ปรับขนาดได้ ส่วนของโปรแกรมสุดท้ายจะมีลักษณะดังนี้:

    ตัวช่วยสร้าง Var, WizardMask, บัฟเฟอร์: Tbitmap; X,Y:จำนวนเต็ม; ... ตัวช่วยสร้าง:=Tbitmap.Create; Wizard.Loadfromfile("spr1.bmp"); WizardMask:=Tbitmap.Create; WizardMask.Loadfromfile("spr2.bmp"); // คัดลอกมาสก์ไปยังบัฟเฟอร์ BitBlt(Buffer.Canvas.Handle,X,Y,50,50, Buffer:=Tbitmap.Create; : WizardMask.Canvas.Handle,0,0,SrcPaint); // คัดลอกสไปรท์ไปยังบัฟเฟอร์ BitBlt(Buffer.Canvas.Handle,X,Y,50,50, Wizard.Canvas.Handle,0,0,SrcAnd); ... // ย้ายบัฟเฟอร์ไปยังรูปแบบ BitBlt(Form1.Canvas.Handle,0,0,320,240, // Buffer.Canvas.Handle,0,0,SrcCopy);

    ธง SrcCopy หมายถึงการคัดลอกโดยไม่มีการเปลี่ยนแปลง คล้ายกับการย้ายหน่วยความจำชิ้นหนึ่งไปยังอีกชิ้นหนึ่ง

    อย่าคิดว่ามาส์กสำเร็จรูปเป็นเรื่องของอดีต เกมคอมพิวเตอร์- ไม่ว่าในกรณีใด หน้ากากจะถูกสร้างขึ้น บางครั้งเท่านั้นที่ทำโดยทางโปรแกรม และบางครั้งก็เตรียมเป็นไฟล์แยกต่างหาก ตัวเลือกใดดีกว่าคุณต้องดูตัวอย่างที่เฉพาะเจาะจง

    ฉันจะไม่อธิบายพารามิเตอร์ทั้งหมดของ BitBlt หากคุณสนใจโปรดดูด้วยตัวคุณเองใน Delphi Help นั่นคือทั้งหมดที่ สุดท้ายนี้ที่มาและภาพของความคิดสร้างสรรค์

    สไปรท์พร้อมหน้ากากซอฟต์แวร์ - โปร่งใส

    อีกวิธีในการแสดงสไปรท์คือวิธีซอฟต์แวร์มาสก์ วิธีนี้จะช้ากว่าเล็กน้อยแต่ไม่ต้องยุ่งยากในการทำมาสก์ นี่ไม่ได้หมายความว่าไม่มีหน้ากากเลย หน้ากากนั้นมีอยู่และสร้างไว้ในความทรงจำ

    สำหรับผู้โชคดีที่เป็นเจ้าของ Windows NT วิธีการที่ใช้ในระบบปฏิบัติการนั้นก็เหมาะสม นี่คือฟังก์ชัน หน้ากากBlt.ตามชื่อของมัน มันช่วยให้คุณแสดงแรสเตอร์โดยใช้บิตมาสก์ได้

    ฉันจะยกตัวอย่างการใช้สไปรท์จากเกม Age of Empires I ให้คุณดู งานของเราเช่นเดียวกับตัวอย่างก่อนหน้านี้คือการแสดงสไปรท์ด้วยสีโปร่งใส (ฟังดูแย่ในภาษารัสเซีย) ในเกมเขาเป็นสีดำ


    var Sprite, Mask: TBitmap; เริ่มสไปรท์:=TBitmap.Create;

    Sprite.LoadFromFile("G0100219.bmp"); หน้ากาก:=TBitmap.Create;จากนั้นคุณสามารถย้ายขั้นตอนที่คุณต้องการไปยังโมดูลของคุณเองได้

    ฉันพบไลบรารีที่เร็วที่สุดสำหรับการทำงานกับกราฟิก - Media Library Component เวอร์ชัน 1.93 ตัวอย่างใช้เพียงบางส่วนเท่านั้น เราต้องการเพียงขั้นตอนเดียวเท่านั้น:

    วาดบิตแมปโปร่งใส(param_1,X,Y,param_2,param_3);

    • param_1 - Canvas ที่จะคัดลอกได้ที่ไหน
    • X,Y - ออฟเซ็ต
    • param_2 - TBitmap สิ่งที่จะคัดลอก
    • param_3 - TColor, สีโปร่งใส - สีนี้จะไม่ถูกคัดลอก

    ไม่จำเป็นต้องใช้เฉพาะไลบรารีนี้เท่านั้น ส่วนประกอบ VCL ของบุคคลที่สามเกือบทุกชุดมีรูทีนหรือฟังก์ชันสำหรับส่งออกบิตแมปโดยใช้สีโปร่งใส ขั้นตอนดังกล่าวมีอยู่ในไลบรารีของ RXLib, LMD Tools, Cool Control และอื่นๆ อีกมากมาย

    สำหรับตัวอย่างของเรา: DrawBitmapTransparent(Buffer.Canvas,WizardX,WizardY,Wizard,clRed); สไปรท์ควรมีลักษณะดังนี้:

    บันทึกย่อเกี่ยวกับความโปร่งใส คุณต้องเลือกสีที่ไม่ได้อยู่บนสไปรท์ ไม่เช่นนั้น "รู" ในภาพจะหลีกเลี่ยงไม่ได้ สิ่งที่ดีที่สุดคือ: #00FF00 - สีเขียวสดใส แต่คุณสามารถใช้สีดำหรือสีขาวก็ได้

    ในบทที่แล้ว “การทำงานของสไปรท์ด้วยหน้ากากสำเร็จรูป” ฉันตั้งค่าการเคลื่อนไหวของสไปรท์เป็นตัวจับเวลา:

    ขั้นตอน TForm1.Timer1Timer (ผู้ส่ง: TObject); เริ่มต้น ... // สิ้นสุดส่วนของร่างกายห่วง

    ใช่ วิธีนี้ดีแต่ไม่เร็วมาก มีตัวเลือกเพิ่มเติมสองสามตัวเลือก:

    1. สร้างเธรด TThread - นี่คือสิ่งที่แสดงในตัวอย่าง
    2. "หยุด" บน IDL

    เรามาพิจารณาวิธีที่สองกันก่อนเพราะ... มีความก้าวหน้าน้อยที่สุด :) เราเขียนขั้นตอนต่อไปนี้:

    ขั้นตอน TForm1.Tic (ผู้ส่ง: TObject; var เสร็จสิ้น: บูลีน); เริ่ม ... // ที่นี่เราป้อนสิ่งที่ต้องดำเนินการ

    ... เสร็จสิ้น:= false; จบ;

    และอีกเล็กน้อย:

    ขั้นตอน TForm1.FormCreate (ผู้ส่ง: TObject); เริ่ม ... Application.OnIdle:= Tic; จบ;

    วิธีนี้เร็วกว่าตัวจับเวลา 1-2 เท่า แต่ก็ไม่ได้ไม่มีข้อเสีย ฉันจะไม่อธิบายว่าทำไม วิธีแรกเป็นวิธีที่เหมาะสมที่สุดสำหรับเกมทั้งที่ซับซ้อนที่สุดและง่ายที่สุด มันถูกนำไปใช้งานโดยใช้เธรด คุณสามารถสร้างได้หลายอันในเกม - อันหนึ่งสำหรับการประมวลผลกราฟิก, อีกอันสำหรับ AI, อันที่สามสำหรับเพลง ฯลฯ แต่ละเธรดมีลำดับความสำคัญของตัวเอง แต่มีเพียงเธรดเดียวเท่านั้นที่มีลำดับความสำคัญสูงสุด เมื่อทำงานกับหลายเธรด อย่าลืมฆ่าเธรดเหล่านั้นเมื่อออกจากโปรแกรม

    ขั้นแรกเราสร้างคลาสใหม่:

    TGameRead=class(TThread) // class สำหรับขั้นตอนการป้องกันตัวจับเวลาเกม ดำเนินการ; แทนที่; // เรียกใช้ขั้นตอน Tic; // หนึ่งขีดของการสิ้นสุดโปรแกรม;

    จากนั้นเป็นตัวแปร:

    วาร์ ... T1:TGameRead; -

    ขั้นตอน TGameRead.execute; เริ่มการซิงโครไนซ์ซ้ำ (Tic);

    จนกว่าจะสิ้นสุด; ขั้นตอน TGameRead.Tic; เริ่ม ... // ที่นี่เราเขียนทุกอย่างเหมือนใน TTimer - OnTime ... end;

    ในเหตุการณ์ Form1.Create เราเริ่มต้นโฟลว์และกำหนดลำดับความสำคัญ ฉันจะไม่อธิบายลำดับความสำคัญทั้งหมด อ่าน Delphi Help ...และอย่าลืมทำความสะอาดตัวเอง:

    T1:=TGameRead.Create(เท็จ); // สร้างเธรด T1.Priority:=TpHighest; // กำหนดลำดับความสำคัญ... ขั้นตอน TForm1.FormDestroy(Sender: TObject); เริ่มต้น T1.Suspend;// ระงับ T1.Free; // และจบมันให้จบ;

    นั่นคือทั้งหมดที่ โอ้ใช่แล้ว คุณคงสนใจสาย FPS ดังนั้นนี่คือสิ่งเดียวกับที่ Quake ให้เมื่อถามถึง "showframerate" หรืออะไรที่คล้ายกัน - จำนวนเฟรมต่อวินาที ทำได้ดังนี้: มีการสร้างตัวแปร:

    ตัวแปร G:จำนวนเต็ม; -

    แต่ละครั้งที่มีการเรียกเธรด Tic เธรดจะเพิ่มขึ้นหนึ่งรายการ:

    ขั้นตอน TGameRead.Tic; เริ่ม ... Inc(G); // เพิ่มมูลค่าของ G end;

    เราสร้างตัวจับเวลาด้วยช่วงเวลา 1,000 - นี่คือ 1 วินาที และในเหตุการณ์ OnTime เราแสดงค่าของ G ในป้ายกำกับ ค่าของ G จะเป็นจำนวนการเรียกขั้นตอน DoSome ใน 1 วินาที:

    ขั้นตอน TForm1.Timer1Timer (ผู้ส่ง: TObject); เริ่ม label1.caption:="FPS:"+IntToStr(G); ก:=0; // รีเซ็ตจุดสิ้นสุด G;โดยเฉลี่ยของฉัน 90-100 เพนเทียม เอเอ็มดี

    233 c Intel 740 8M - เอาต์พุต

    เฟรมต่อวินาที ด้วยหน้าต่าง 360X360 เริ่มต้นได้ไม่เลว! แหล่งที่มารูปภาพอยู่ตรงหน้าคุณ ป.ล. คุณอาจมีคำถาม - ทำไมสไปรท์จึงเคลื่อนที่ไปด้านหลังเมาส์? คำตอบ: ค่าใช้จ่ายในการเขียนโปรแกรมทดสอบต่ำที่สุดพร้อมการเคลื่อนไหวที่หลากหลายการใช้งาน ขั้นตอนภายนอก:

    สำหรับเอาต์พุตสไปรท์แบบโปร่งใส ดีแต่ก็มีข้อเสียอยู่หลายประการ

    วิธีนี้ ประการแรก ขั้นตอนเหล่านี้ไม่ได้รับการปรับให้เหมาะสมที่สุด - จุดประสงค์หลักคือเพื่อแสดงองค์ประกอบแอปพลิเคชันที่เรียบง่าย เช่น ไอคอน รูปภาพปุ่ม ฯลฯ แม้ว่าสิ่งนี้ใช้ไม่ได้กับบางไลบรารี แต่โค้ดคือแอสเซมเบลอร์ 90%ประการที่สอง คุณต้องจัดเก็บอิมเมจเอาต์พุตไว้

    ไฟล์บีเอ็มพี

    แม้ว่าไฟล์อื่นๆ ที่ไม่ได้ใช้การบีบอัดข้อมูลแบบสูญเสีย (Jpeg) ก็ตาม หากมีมากกว่าหนึ่งภาพและระหว่างแอนิเมชั่นปกติจะมีประมาณ 150-200 ภาพต่อหน่วย ก็ยากที่จะได้ส่วนที่ต้องการของไฟล์อย่างแน่นอน

    ผมขอยกตัวอย่างให้คุณฟัง

    ไฟล์ BMP มี 8 รูปภาพ - 64x64 พิกเซล คุณต้องเข้าถึงภาพที่ 6 (ทำเครื่องหมายด้วยสี่เหลี่ยมสีชมพูในรูป) - พิกัดของมันคือ 128.64

    การใช้ส่วนประกอบนี้ คุณไม่จำเป็นต้องคำนึงถึงพิกัดของภาพหรือสีโปร่งใส เนื่องจากสามารถแก้ปัญหาสองปัญหาได้ในคราวเดียว

    มาดูสิ่งที่ต้องทำเพื่อแสดงสไปรท์โดยใช้ TImageList ขั้นแรก คุณต้องโหลดชุดสไปรต์ TImageList เพื่อเป็นการดีที่สุดที่จะใช้คำสั่ง:

    TImageList.AddMasked (รูปภาพ: TBitmap; MaskColor: TColor): จำนวนเต็ม;

    พารามิเตอร์แรกคือบิตแมป สีโปร่งใสตัวที่สองคือสีโปร่งใส หากคุณไม่จำเป็นต้องใช้สีโปร่งใส คุณจะต้องใช้ขั้นตอนเพิ่ม หลังจากดาวน์โหลดรูปภาพทั้งหมดแล้ว คุณสามารถเริ่มแสดงรูปภาพเหล่านั้นบนหน้าจอได้ มีขั้นตอนดังนี้:

    ขั้นตอน TImageList.Draw (Canvas: TCanvas; X, Y, Index: Integer);

    พารามิเตอร์ Canvas ตัวแรกที่จะทำการวาด พิกัดที่สองและสามสำหรับเอาต์พุต X และ Y และดัชนีที่สี่หรือ หมายเลขซีเรียลภาพที่ส่งออก

    ตัวอย่างเช่น:

    ImageList1.Draw (แคนวาส,0,0,6);

    BitBlt(Canvas.Handle,0,0,64,64,Bitmap_Mask.Canvas.Handle,128,64,SrcPaint); - หน้ากาก BitBlt(Canvas.Handle,0,0,64,64,Bitmap.Canvas.Handle,128,64,SrcAnd; - สไปรท์

    ImageList1.Draw (แคนวาส,0,0,6);

    สิ่งเดียวกัน แต่ใช้ BitBlt:

    BitBlt(Canvas.Handle,0,0,64,64,Bitmap_Mask.Canvas.Handle,128,64,SrcPaint); - หน้ากาก BitBlt(Canvas.Handle,0,0,64,64,Bitmap.Canvas.Handle,128,64,SrcAnd; - สไปรท์

    ฉันคิดว่าไม่จำเป็นต้องอธิบายว่าการใช้ TImageList นั้นดีกว่าและง่ายกว่า ตัวอย่างการทำงานกับ TImageList อธิบายไว้ในไฟล์ มันแสดงแอนิเมชั่นตัวละครจากเกม WarCraft และ Warlord III ฉันยังไม่ทราบว่ากลไกการเรนเดอร์ใน TImageList ทำงานอย่างไร การขุดของฉันนำไปสู่ฟังก์ชันนี้:

    ฟังก์ชั่น ImageList_Draw (ImageList: HImageList; ดัชนี: จำนวนเต็ม; ปลายทาง: HDC; X, Y: จำนวนเต็ม; สไตล์: UINT): บูล; stdcall;

    ฟังก์ชั่น ImageList_DrawEx (ImageList: HImageList; ดัชนี: จำนวนเต็ม; ปลายทาง: HDC; X, Y, DX, DY: จำนวนเต็ม; Bk, Fg: TColorRef; สไตล์: พระคาร์ดินัล): บูล; stdcall;

    HImageList - จัดการกับ TImageList

    เนื่องจากมีการเรียกขั้นตอนการส่งออกที่อยู่ในไลบรารี Comctl32.dll จึงยังไม่ชัดเจนว่าอัลกอริทึมใดที่ใช้เพื่อแสดงรูปภาพ บอกได้คำเดียวว่าเมื่อเพิ่มรูปภาพใหม่ทั้งรูปภาพและมาสก์จะถูกเพิ่มเข้าไป

    ฉันเริ่มสนใจปัญหานี้และเจาะลึกไลบรารีและส่วนประกอบมาตรฐานของ Windows ต่อไป ข้อมูลเกี่ยวกับปัญหาเหล่านี้อาจมีอยู่ใน SDK จำนวนมากที่ Microsoft เปิดตัว ในองค์ประกอบ TFastDIB ฉันเจอขั้นตอน Draw:

    ขั้นตอน TFastDIB.MaskDraw(fDC,x,y:Integer;c:TFColor); เริ่ม TransBlt(fDC,x,y,ความกว้าง,ความสูง,hDC,0,0,ความกว้าง,ความสูง,PDWord(@c)^); จบ;

    โดยปกติแล้วฉันสนใจขั้นตอน TransBlt และนี่คือสิ่งที่ฉันพบ:

    ฟังก์ชั่น TransBlt(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11:DWord):BOOL; stdcall; ...ฟังก์ชั่น CreateDIB; ภายนอก "gdi32.dll" ชื่อ "CreateDIBSection"; ฟังก์ชั่น TransBlt; ภายนอก "msimg32.dll" ชื่อ "TransparentBlt"; ฟังก์ชั่น AlphaBlt; ชื่อ "msimg32.dll" ภายนอก "AlphaBlend";

    ฉันอยากรู้ว่าไลบรารี “msimg32.dll” สามารถทำอะไรได้อีกบ้าง และนี่คือรายการทั้งหมด:

    • อัลฟ่าเบลนด์
    • การไล่ระดับสีเติม
    • โปร่งใสBlt
    • Dll เตรียมใช้งาน
    • vSetDrawflag

    ก็พอแล้ว ไม่อย่างนั้นผู้อ่านบางคนก็ยังไม่เข้าใจอะไรเลย แต่สำหรับผู้ที่สนใจ ฉันจะบอกว่าขั้นตอนและฟังก์ชันทั้งหมดไม่ได้อธิบายไว้ใน Delphi มากนัก

    การใช้ไดเร็คเอ็กซ์

    สิ่งที่ไม่ดีเกี่ยวกับวิธีการส่งออกสไปรท์ที่กล่าวถึงข้างต้นก็คือมันช้า ฉันอยากจะย้ำว่าในแต่ละโปรแกรมคุณต้องเลือกวิธีการเขียนของคุณเอง งานเฉพาะเจาะจงต้องใช้วิธีดำเนินการของตนเอง ความจริงที่ว่า Microsoft เขียนไลบรารี Direct X ไม่ได้หมายความว่าคุณจะต้องเขียนกราฟิกทั้งหมดโดยใช้ไลบรารีนั้นทันที

    ผมขอยกตัวอย่างให้คุณฟัง เกมยอดนิยมสำหรับ Windows - Quake II, Warcraft, Diablo - ไม่มี MINE MINE และ SOLITAIRE คุณอาจไม่เชื่อ แต่นี่คือข้อเท็จจริง ประเภทแรกเล่นโดยคนจำนวนจำกัด ส่วนประเภทหลังเล่นโดยทุกคน ฉันพูดแบบนี้เพราะถ้าคุณเขียน แอปพลิเคชั่นกราฟิกจากนั้นคุณต้องมุ่งเน้นไปที่ความต้องการของเขาและเลือกเทคโนโลยีที่เหมาะสมขึ้นอยู่กับพวกเขา ความต้องการเหล่านี้คืออะไร:

    จำเป็นต้องถอนตัว ปริมาณมากเปลี่ยนภาพบ่อยๆ
    ข้อมูลกราฟิกจำนวนมาก
    การสนับสนุนฮาร์ดแวร์
    ประสิทธิภาพสูงสุด

    การใช้ Direct X คุณจะได้รับทุกสิ่งที่กล่าวมาข้างต้น เดิมทีชุดของไลบรารีเหล่านี้ได้รับการพัฒนาให้เป็นเครื่องมือสำหรับการทำงานกับกราฟิก เกิดอะไรขึ้นเมื่อพวกเขาเขียนภายใต้ DOS: พวกเขาสร้างภาพบางประเภทในพื้นที่หน่วยความจำ (บัฟเฟอร์ด้านหลัง) หรือคัดลอกสไปรท์ไว้ที่นั่น จากนั้นย้ายบัฟเฟอร์ด้านหลังนี้ไปยังพื้นที่หน่วยความจำ "หน้าจอ" หน้าจอทั้งหมดถูกวาดพร้อมกัน ด้วยการถือกำเนิดของ Windows จึงไม่สามารถย้ายชิ้นส่วนหน่วยความจำไปยังบริเวณหน้าจอได้ ต้องใช้ผ้าใบ หูจับ

    DirectX แก้ปัญหาเหล่านี้ได้ทั้งหมด คุณสามารถเตรียมภาพบนพื้นผิวที่เรียกว่า จากนั้น FLIP และพื้นผิวทั้งหมดจะมองเห็นได้ - คัดลอกไปยังพื้นที่หน่วยความจำวิดีโอบนหน้าจอ ฉันควรทราบว่าอัลกอริทึมการทำงานไม่เปลี่ยนแปลงเลย

    ด้วยการถือกำเนิดของ DirectX การสนับสนุนฮาร์ดแวร์สำหรับสิ่งที่จำเป็นเช่นสีโปร่งใสและการลบบิตก็ปรากฏขึ้น

    คำว่า bit-blitting หมายถึงกระบวนการย้ายกลุ่มของบิต (รูปแบบ) จากตำแหน่งหนึ่งบนหน้าจอไปยังอีกตำแหน่งหนึ่งหรือในหน่วยความจำ ในเกมพีซี เราสนใจที่จะย้ายภาพจากพื้นที่จัดเก็บข้อมูลนอกหน้าจอไปยังพื้นที่บัฟเฟอร์วิดีโอ หากคุณสนใจความสามารถด้านฮาร์ดแวร์ของการ์ดแสดงผลของคุณ คุณสามารถค้นหาได้โดยรับ Microsoft DirectX CPL ในนั้นคุณสามารถดูได้ว่าฟังก์ชันใดในการ์ดแสดงผลที่ใช้ในฮาร์ดแวร์และซอฟต์แวร์ใดบ้าง

    ดังนั้นกระบวนการทำงานจึงเป็นดังนี้: โหลดสไปรท์ลงบนพื้นผิว (ISurface) จากนั้นคุณต้องเรียกขั้นตอน BLT หรือ BLTFAST จากนั้นเปลี่ยนบัฟเฟอร์และพื้นผิวที่มองเห็นด้วยคำสั่ง FLIP เท่านี้ก็เรียบร้อย

    ในตอนต้นของส่วนนี้ฉันเขียน Direct X แต่ฉันค่อนข้างหลอกคุณ ฉันจะแสดงวิธีแสดงสไปรท์โดยใช้ Direct X แต่ใช้ชุดส่วนประกอบ DelphiX VCL ฉันทำสิ่งนี้ด้วยเหตุผลง่ายๆ ว่าถ้าฉันเขียนตัวอย่างโดยใช้โมดูล DirectX มาตรฐาน บางคนจะไม่เข้าใจพวกเขา สิ้นหวังและเลิกเขียนโปรแกรมไปเลย :) เห็นด้วย ไม่ใช่ทุกคนจะเข้าใจทันทีว่ามันทำอะไร ขั้นตอนนี้แม้ว่าจะเปลี่ยนแค่พื้นผิวก็ตาม

    var hRet: HRESULT; เริ่มต้นผลลัพธ์:= เท็จ;<>ในขณะที่ True จะเริ่มต้น hRet:= FDDDSPrimary.Flip(nil, 0);<>ถ้า hRet = DD_OK ให้แตกอย่างอื่น ถ้า hRet = DDERR_SURFACELOST ให้เริ่ม hRet:= RestoreAll;

    ถ้า hRet

    DD_OK จากนั้นออก; จบอย่างอื่นถ้า hRet DDERR_WASSTILLDRAWING จากนั้นออก จบ; ผลลัพธ์:= จริง; จบ;.

    นั่นเป็นเหตุผลที่ฉันตัดสินใจใช้ การเขียนด้วยมันง่ายมาก เราต้องการเพียงสององค์ประกอบเท่านั้น TDXDraw แรก - เพื่ออธิบายสั้น ๆ มันเป็นอะนาล็อกของ TCanvas องค์ประกอบอื่นคือ TDXImageList ซึ่งเป็นอะนาล็อกโดยตรงของ TImageList เฉพาะองค์ประกอบทั้งหมดเท่านั้นที่เป็น TDIB และไม่มีมาสก์ใดๆประมาณหนึ่งสัปดาห์ที่ผ่านมา สมาชิกคนหนึ่งของฉันขอให้ฉันพูดคุยเกี่ยวกับ สไปรต์ CSSโดยทั่วไปมีอะไรบ้าง และรับประทานกับอะไร ดังนั้นวันนี้ฉันจึงตัดสินใจเขียนบทความนี้ซึ่งฉันจะบอกคุณ CSS sprites คืออะไรและใช้ที่ไหน? CSS สไปรท์ - นี่คือภาพที่รวมกันซึ่งมีหลายภาพรูปภาพต่างๆ และการใช้ทรัพย์สินตำแหน่งพื้นหลัง 2 เราจัดแสดง 2 รูปภาพที่ต้องการ วีในสถานที่ที่เหมาะสม 2 รูปภาพที่ต้องการ - สมมติว่าเรามีปุ่ม และปุ่มนี้จะเปลี่ยนรูปลักษณ์เมื่อคุณวางเคอร์เซอร์ของเมาส์ไว้เหนือปุ่มนั้น คุณสามารถทำได้ เช่นรูปภาพแล้วแทนที่รูปภาพหนึ่งหรือรูปภาพอื่นเป็นพื้นหลังของปุ่ม แต่ข้อเสียของวิธีนี้ชัดเจน: 2 รูปภาพที่ต้องการ ครั้งไฟล์เพิ่มเติม 1 , ประมาณ ขนาดใหญ่ขึ้นดังนั้นใน 2 พื้นหลังของปุ่ม

    เพื่อให้ชัดเจนยิ่งขึ้น เรามาแก้ไขปัญหานี้กัน เรามีรูปภาพที่มีส่วนสูง 20 พิกเซลและความกว้าง 100 พิกเซล ปุ่มมีความกว้าง 50 พิกเซลและความสูง 20 พิกเซล ในภาพหนึ่งเราวางภาพของทั้งสองรัฐ (ทีละภาพ) รหัส HTMLจะเป็นเช่นนี้:

    ปุ่ม

    และ รหัสซีเอสเอส:

    เอ (
    พื้นหลัง: url("button.jpg") ไม่ซ้ำด้านบนซ้าย; // พื้นหลังของปุ่ม
    จอแสดงผล: บล็อก; // ทำ องค์ประกอบบล็อก
    ความสูง: 20px; // ความสูงของปุ่ม
    ความกว้าง: 50px; // ความกว้างของปุ่ม
    การตกแต่งข้อความ: ไม่มี; // ลบขีดเส้นใต้ออก
    }
    a:โฮเวอร์ (
    ตำแหน่งพื้นหลัง: ด้านบนขวา; // เปลี่ยนตำแหน่งพื้นหลังเพื่อให้รูปภาพชดเชย
    }

    ด้วยวิธีที่ชาญฉลาดนี้ คุณสามารถจัดเก็บภาพหลายภาพไว้ในภาพเดียวได้ ฉันขอเน้นย้ำว่ามันเป็นชุดของภาพที่แม่นยำ ไม่ใช่เพียงเท่านั้น 2 - บางครั้งเกือบทั้งไซต์ประกอบด้วยรูปภาพเดียว ซึ่งประกอบด้วยรูปภาพทั้งหมดที่ใช้ ฉันไม่คิดว่าสิ่งนี้จะดีนัก แต่จะมีไฟล์รูปภาพจำนวนขั้นต่ำและ ขนาดขั้นต่ำกำลังโหลดหน้าซึ่งดีอยู่เสมอ

    ก่อนที่ pseudo-class:hover จะปรากฏใน CSS การสร้างโรลโอเวอร์ซึ่งเป็นองค์ประกอบที่เปลี่ยนรูปลักษณ์เมื่อวางเมาส์เหนือ - ถูกนำมาใช้ผ่าน ภาษาจาวาสคริปต์- ในปัจจุบันนี้ทำได้ง่ายกว่ามาก แต่มีข้อเสียอยู่ประการหนึ่ง: หากภาพพื้นหลังบางรูปควรปรากฏในสถานะ:hover (เช่น เมื่อวางเคอร์เซอร์ไว้เหนือองค์ประกอบ) รูปภาพจะเริ่มโหลดในขณะที่เคอร์เซอร์ถูกโฮเวอร์ และไม่ เมื่อไร โหลดทั้งหมดหน้า

    ด้วยเหตุนี้ จึงอาจมีความล่าช้าเล็กน้อยเมื่อภาพปรากฏขึ้นเป็นครั้งแรก และแม้ว่าความล่าช้านี้จะไม่เกิดขึ้นกับการเลื่อนเคอร์เซอร์ที่ตามมาทั้งหมดอีกต่อไป แต่นักพัฒนาจำนวนมากก็คิดเกี่ยวกับวิธีการแก้ไขปัญหานี้ ตัวอย่างเช่นด้วย โดยใช้จาวาสคริปต์คุณสามารถมั่นใจได้ว่าภาพพื้นหลังทั้งหมดจะถูกโหลดไว้ล่วงหน้า แต่มีวิธีที่ไม่จำเป็นต้องมีความรู้เกี่ยวกับภาษาการเขียนโปรแกรมและก็คือการใช้สไปรท์

    CSS สไปรต์คืออะไร

    สไปรท์ CSS เป็นไฟล์กราฟิกเดียวที่มีรูปภาพต่างๆ มากมาย มันสามารถประกอบด้วยองค์ประกอบอินเทอร์เฟซแบบกราฟิกทั้งหมด เช่น ไอคอน ปุ่ม ฯลฯ นอกจากนี้ สไปรท์มักจะรวมภาพพื้นหลังพร้อมกับรูปแบบต่างๆ สำหรับสถานะ:โฮเวอร์ ตัวอย่างทั่วไปสไปรท์:

    สไปรท์ ซึ่งมีไอคอนทั้งหมดที่ใช้สไปรท์กับไอคอนโซเชียลเน็ตเวิร์กและรูปแบบต่างๆ สำหรับ: โฮเวอร์

    ประโยชน์ของ CSS สไปรท์

    • สไปรท์ CSS ประกอบด้วย ภาพพื้นหลังสำหรับสถานะต่างๆ ขององค์ประกอบ และจะถูกโหลดทั้งหมดเมื่อโหลดหน้าเว็บ วิธีนี้จะป้องกันไม่ให้โรลโอเวอร์ช้าลงเมื่อคุณวางเมาส์เหนือองค์ประกอบเป็นครั้งแรก
    • จำนวนการเรียกไปยังเซิร์ฟเวอร์ลดลง ท้ายที่สุดแล้ว การโหลดไอคอนขนาดเล็กแต่ละไอคอนจำเป็นต้องมีคำขอแยกกัน และยิ่งคำขอน้อยลงก็ยิ่งดีเท่านั้น หากต้องการดาวน์โหลดสไปรท์ คุณจำเป็นต้องมีคำขอเดียวไปยังเซิร์ฟเวอร์
    • ข้อดีอีกประการหนึ่งของการจัดเก็บรูปภาพจำนวนมากในรูปแบบสไปรท์ก็คือ หากรูปภาพเหล่านั้นมีจานสีที่คล้ายคลึงกัน ก็จะเป็นเช่นนั้น ภาพขนาดใหญ่จะมีน้ำหนักน้อยกว่าภาพเล็กๆ แต่ละภาพรวมกัน
    • โดยทั่วไปทั้งหมดนี้มีผลดีต่อความเร็วในการโหลดไซต์

    วิธีสร้างสไปรท์จากรูปภาพ

    ในกรณีคลาสสิก สไปรท์จะถูกสร้างขึ้นในโปรแกรมแก้ไขรูปภาพ รูปภาพขนาดเล็กจะถูกวางตามลำดับบนผืนผ้าใบขนาดใหญ่ (มักมี พื้นหลังโปร่งใส) ซึ่งจะถูกบันทึกเป็นไฟล์กราฟิก

    วิธีการสร้างสไปรท์ด้วยตนเองนั้นค่อนข้างใช้เวลานาน ดังนั้นเมื่อการใช้สไปรท์เริ่มได้รับแรงผลักดัน บริการออนไลน์สำหรับ การสร้างอัตโนมัติภาพต่อเรียง เช่น สไปรท์เกน, RetinaSpriteGeneratorและอื่น ๆ คุณอัปโหลดภาพที่ต้องการไปที่ แยกไฟล์ไปยังไซต์ และสร้างสไปรท์ให้คุณ ซึ่งคุณสามารถดาวน์โหลดลงคอมพิวเตอร์ของคุณได้ทันที

    วิธีใช้ CSS สไปรท์

    ตอนนี้ได้เวลาเรียนรู้วิธีใช้ CSS Sprites ในทางปฏิบัติแล้ว เราจะแสดงตัวอย่างเล็กๆ ให้กับคุณโดยใช้ไอคอนที่มีสไปรท์ เครือข่ายสังคมออนไลน์(เราแสดงให้เห็นข้างต้น) ในสถานะลิงก์ปกติ ไอคอนโซเชียลเน็ตเวิร์กจะเป็นสี ( แถวบนสุด sprite) และเมื่อคุณวางเคอร์เซอร์ไว้ เคอร์เซอร์จะเปลี่ยนเป็นสีเทา (ดังเช่นในแถวล่างสุด)

    มาร์กอัป HTML มีลักษณะดังนี้:

    เราสร้างชั้นเรียนของเราเองเพื่อเชื่อมโยงกับแต่ละโซเชียลเน็ตเวิร์ก เนื่องจากนี่คือตัวอย่างการทดสอบ เราจึงไม่เสียเวลาในการกรอกแอตทริบิวต์ href - แทนที่จะใส่ลิงก์ไปยังไซต์จริง เราใส่ตัวยึดตำแหน่ง ภายในแท็ก เราไม่โพสต์อะไรเพราะว่า รูปร่างลิงก์จะตอบสนองด้วยภาพพื้นหลังพร้อมไอคอนโซเชียลมีเดีย

    เรามาต่อกันที่ CSS กันดีกว่า ก่อนอื่น เรามาเขียนสไตล์ทั่วไปสำหรับลิงก์ทั้งหมดกันก่อน:

    A ( background-image: url(https://goo.gl/1t18Rz); background-repeat: no-repeat; height: 98px; width: 100px; display: inline-block; margin-right: 10px; )

    สองบรรทัดถัดไปคือความสูงและความกว้างของแต่ละองค์ประกอบ - ค่านิยมเหล่านี้ถูกกำหนดอย่างไร? ที่นี่เราเริ่มต้นจากขนาดของไอคอนในสไปรท์ ความสูงของแต่ละไอคอนคือ 98 พิกเซล และความกว้างคือ 100 พิกเซล ต่อไป เราจะวางตำแหน่งภาพพื้นหลังของแต่ละลิงก์ โดยปรับพื้นหลังเพื่อให้ไอคอนพอดีกับ "หน้าต่าง" ของลิงก์ขนาด 98x100 พิกเซลทุกประการ

    A.facebook ( ตำแหน่งพื้นหลัง: ซ้ายบน; )

    ไปกันต่อ: วางตำแหน่งพื้นหลังสำหรับลิงก์ Twitter ไอคอน Twitter อยู่ในตำแหน่งทางด้านขวาของ Facebook และขนาบข้างโดยไม่สร้างช่องว่างใดๆ เราจำเป็นต้องย้ายสไปรท์ไปทางพิกเซลด้านซ้ายเพียงพอเพื่อซ่อนไอคอน Facebook และเติมพื้นที่ลิงก์ด้วยไอคอน Twitter ให้สมบูรณ์ เนื่องจากความกว้างของแต่ละไอคอนคือ 100 พิกเซล เราจึงเลื่อนพื้นหลังไปทางซ้าย 100 พิกเซล เรายังไม่ได้เปลี่ยนตำแหน่งแนวตั้งแต่อย่างใด แต่จะคงค่าไว้ด้านบน:

    A.twitter (ตำแหน่งพื้นหลัง: -100px ด้านบน; )

    เราจะดำเนินการที่คล้ายกันกับลิงก์ที่เหลือ โดยเพิ่มอีก 100 พิกเซลในแต่ละตำแหน่งแนวนอนที่ตามมา ดังนั้นจึงย้ายสไปรท์ไปทางซ้ายมากขึ้นเรื่อยๆ คุณจะได้ภาพนี้:

    A.youtube ( ตำแหน่งพื้นหลัง: -200px ด้านบน; ) a.instagram ( ตำแหน่งพื้นหลัง: -300px ด้านบน; ) a.linkedin ( ตำแหน่งพื้นหลัง: -400px ด้านบน; ) a.tumblr ( ตำแหน่งพื้นหลัง: -500px ด้านบน ; ) a.google ( ตำแหน่งพื้นหลัง: -600px ด้านบน; )

    ผลลัพธ์ของรหัสนี้แสดงอยู่ในภาพหน้าจอด้านล่าง:


    ทีนี้มาดูพฤติกรรมกัน ภาพพื้นหลังเมื่อคุณวางเมาส์เหนือลิงก์ เราจำเป็นต้องเลื่อนสไปรท์ขึ้นในแนวตั้งเพื่อให้ไอคอนจากแถวล่างสุดของสไปรท์ตกลงไปในพื้นที่การดู ทุกสิ่งที่นี่ค่อนข้างง่ายและสามารถแก้ไขได้ด้วยสิ่งเดียว กฎ CSSกล่าวคือโดยการกำหนดค่าด้านล่างให้กับคุณสมบัติ background-position-y:

    A:โฮเวอร์ ( ตำแหน่งพื้นหลัง-y: ด้านล่าง; )

    ในกรณีของเรา สไตล์นี้สามารถเขียนได้สำหรับลิงก์ทั้งหมด และจะทำงานได้อย่างถูกต้อง อย่างไรก็ตาม ในสถานการณ์อื่นๆ ที่องค์ประกอบในสไปรท์อยู่ในลำดับที่แตกต่างกัน คุณอาจต้องเขียนโค้ดเพิ่มเติม

    ดูการสาธิตด้านล่างสำหรับผลลัพธ์ของการทำงานของสไปรท์ (เพื่อให้ตัวอย่างสวยงามยิ่งขึ้น เราได้ทำให้การเลื่อนพื้นหลังนุ่มนวลขึ้นเมื่อวางเคอร์เซอร์):


    หากคุณสนใจ นี่คือบรรทัดที่รับผิดชอบในการเปลี่ยนแปลงไอคอนอย่างราบรื่น (ไม่ต้องกังวล อีกไม่นานเราจะศึกษาภาพเคลื่อนไหว CSS และโดยเฉพาะคุณสมบัติการเปลี่ยนแปลง):

    A ( การเปลี่ยนแปลง: การคลายออกทั้งหมด 0.2 วินาที; )

    ตอนนี้คุณรู้แล้วว่า CSS Sprite คืออะไร และมีประโยชน์อย่างไร นอกจากการป้องกันความล่าช้าในการโหลดภาพพื้นหลังแล้ว การใช้สไปรท์ยังช่วยลดภาระบนเซิร์ฟเวอร์อีกด้วย นอกจากนี้นี้ วิธีที่สะดวกเก็บองค์ประกอบส่วนต่อประสานกราฟิกทั้งหมดไว้ในที่เดียว

    ดังนั้นเราจึงได้ดูวิธีการหลักในการจัดรูปแบบลิงก์แล้ว เราขอแนะนำให้คุณฝึกฝนเพิ่มเติมเพื่อรวบรวมความรู้ที่คุณได้รับ และบทต่อไปของหนังสือของเราเกี่ยวกับแอนิเมชั่น CSS ซึ่งการนำไปปฏิบัตินั้นเกิดขึ้นได้เนื่องจากคุณสมบัติที่ปรากฏใน CSS3 และในบทเรียนแรก เราจะวิเคราะห์คุณสมบัติการเปลี่ยนแปลง -